Clean up variables and formatting

This commit is contained in:
Veronica Berglyd Olsen
2024-01-28 00:28:01 +01:00
parent 97b791511f
commit 8e4e6903b1
41 changed files with 1241 additions and 1248 deletions
+16 -16
View File
@@ -213,17 +213,17 @@ def formatInt(value: int) -> str:
if not isinstance(value, int): if not isinstance(value, int):
return "ERR" return "ERR"
theVal = float(value) fVal = float(value)
if theVal > 1000.0: if fVal > 1000.0:
for pF in ["k", "M", "G", "T", "P", "E"]: for pF in ["k", "M", "G", "T", "P", "E"]:
theVal /= 1000.0 fVal /= 1000.0
if theVal < 1000.0: if fVal < 1000.0:
if theVal < 10.0: if fVal < 10.0:
return f"{theVal:4.2f}{nwUnicode.U_THSP}{pF}" return f"{fVal:4.2f}{nwUnicode.U_THSP}{pF}"
elif theVal < 100.0: elif fVal < 100.0:
return f"{theVal:4.1f}{nwUnicode.U_THSP}{pF}" return f"{fVal:4.1f}{nwUnicode.U_THSP}{pF}"
else: else:
return f"{theVal:3.0f}{nwUnicode.U_THSP}{pF}" return f"{fVal:3.0f}{nwUnicode.U_THSP}{pF}"
return str(value) return str(value)
@@ -275,22 +275,22 @@ def transferCase(source: str, target: str) -> str:
"""Transfers the case of the source word to the target word. This """Transfers the case of the source word to the target word. This
will consider all upper or lower, and first char capitalisation. will consider all upper or lower, and first char capitalisation.
""" """
theResult = target result = target
if not isinstance(source, str) or not isinstance(target, str): if not isinstance(source, str) or not isinstance(target, str):
return theResult return result
if len(target) < 1 or len(source) < 1: if len(target) < 1 or len(source) < 1:
return theResult return result
if source.istitle(): if source.istitle():
theResult = target.title() result = target.title()
if source.isupper(): if source.isupper():
theResult = target.upper() result = target.upper()
elif source.islower(): elif source.islower():
theResult = target.lower() result = target.lower()
return theResult return result
def fuzzyTime(seconds: int) -> str: def fuzzyTime(seconds: int) -> str:
+2 -6
View File
@@ -235,16 +235,12 @@ class BuildSettings:
def getInt(self, key: str) -> int: def getInt(self, key: str) -> int:
"""Type safe value access for integers.""" """Type safe value access for integers."""
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1]) value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
if isinstance(value, (int, float)): return int(value) if isinstance(value, (int, float)) else 0
return int(value)
return 0
def getFloat(self, key: str) -> float: def getFloat(self, key: str) -> float:
"""Type safe value access for floats.""" """Type safe value access for floats."""
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1]) value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
if isinstance(value, (int, float)): return float(value) if isinstance(value, (int, float)) else 0.0
return float(value)
return 0.0
## ##
# Setters # Setters
+19 -22
View File
@@ -279,28 +279,25 @@ class DocDuplicator:
"""Run through a list of items, duplicate them, and copy the """Run through a list of items, duplicate them, and copy the
text content if they are documents. text content if they are documents.
""" """
if not items: if items:
return nHandle = items[0]
hMap: dict[str, str | None] = {t: None for t in items}
nHandle = items[0] for tHandle in items:
hMap: dict[str, str | None] = {t: None for t in items} newItem = self._project.tree.duplicate(tHandle)
for tHandle in items: if newItem is None:
newItem = self._project.tree.duplicate(tHandle)
if newItem is None:
return
hMap[tHandle] = newItem.itemHandle
if newItem.itemParent in hMap:
newItem.setParent(hMap[newItem.itemParent])
self._project.tree.updateItemData(newItem.itemHandle)
if newItem.isFileType():
oldDoc = self._project.storage.getDocument(tHandle)
newDoc = self._project.storage.getDocument(newItem.itemHandle)
if newDoc.fileExists():
return return
newDoc.writeDocument(oldDoc.readDocument() or "") hMap[tHandle] = newItem.itemHandle
yield newItem.itemHandle, nHandle if newItem.itemParent in hMap:
nHandle = None newItem.setParent(hMap[newItem.itemParent])
self._project.tree.updateItemData(newItem.itemHandle)
if newItem.isFileType():
oldDoc = self._project.storage.getDocument(tHandle)
newDoc = self._project.storage.getDocument(newItem.itemHandle)
if newDoc.fileExists():
return
newDoc.writeDocument(oldDoc.readDocument() or "")
yield newItem.itemHandle, nHandle
nHandle = None
return return
# END Class DocDuplicator # END Class DocDuplicator
@@ -313,7 +310,7 @@ class ProjectBuilder:
def __init__(self) -> None: def __init__(self) -> None:
self._path = None self._path = None
self.tr = partial(QCoreApplication.translate, "NWProject") self.tr = partial(QCoreApplication.translate, "ProjectBuilder")
return return
@property @property
+2 -2
View File
@@ -248,8 +248,8 @@ class NWBuildDocument:
def _setupBuild(self, bldObj: Tokenizer) -> dict: def _setupBuild(self, bldObj: Tokenizer) -> dict:
"""Configure the build object.""" """Configure the build object."""
# Get Settings # Get Settings
textFont = self._build.getStr("format.textFont") textFont = self._build.getStr("format.textFont")
textSize = self._build.getInt("format.textSize") textSize = self._build.getInt("format.textSize")
fontFamily = textFont or CONFIG.textFont fontFamily = textFont or CONFIG.textFont
bldFont = QFont(fontFamily, textSize) bldFont = QFont(fontFamily, textSize)
+6 -6
View File
@@ -52,7 +52,7 @@ class NWDocument:
def __init__(self, project: NWProject, tHandle: str | None) -> None: def __init__(self, project: NWProject, tHandle: str | None) -> None:
self._project = project self._project = project
self._item = None # The currently open item self._item = None # The currently open item
self._handle = None # The handle of the currently open item self._handle = None # The handle of the currently open item
@@ -284,12 +284,12 @@ class NWDocument:
"""Parse the document meta tag and return the name, parent, """Parse the document meta tag and return the name, parent,
class and layout meta values. class and layout meta values.
""" """
theName = self._docMeta.get("name", "") name = self._docMeta.get("name", "")
theParent = self._docMeta.get("parent", None) parent = self._docMeta.get("parent", None)
theClass = self._docMeta.get("class", None) itemClass = self._docMeta.get("class", None)
theLayout = self._docMeta.get("layout", None) itemLayout = self._docMeta.get("layout", None)
return theName, theParent, theClass, theLayout return name, parent, itemClass, itemLayout
def getError(self) -> str: def getError(self) -> str:
"""Return the last recorded exception.""" """Return the last recorded exception."""
+4 -4
View File
@@ -122,8 +122,8 @@ class NWIndex:
for nwItem in self._project.tree: for nwItem in self._project.tree:
if nwItem.isFileType(): if nwItem.isFileType():
tHandle = nwItem.itemHandle tHandle = nwItem.itemHandle
theDoc = self._project.storage.getDocument(tHandle) doc = self._project.storage.getDocument(tHandle)
self.scanText(tHandle, theDoc.readDocument() or "", blockSignal=True) self.scanText(tHandle, doc.readDocument() or "", blockSignal=True)
self._indexBroken = False self._indexBroken = False
SHARED.indexSignalProxy({"event": "buildIndex"}) SHARED.indexSignalProxy({"event": "buildIndex"})
return return
@@ -148,8 +148,8 @@ class NWIndex:
""" """
if tHandle and self._project.tree.checkType(tHandle, nwItemType.FILE): if tHandle and self._project.tree.checkType(tHandle, nwItemType.FILE):
logger.debug("Re-indexing item '%s'", tHandle) logger.debug("Re-indexing item '%s'", tHandle)
theDoc = self._project.storage.getDocument(tHandle) doc = self._project.storage.getDocument(tHandle)
self.scanText(tHandle, theDoc.readDocument() or "") self.scanText(tHandle, doc.readDocument() or "")
return True return True
return False return False
+4 -4
View File
@@ -194,12 +194,12 @@ class Tokenizer(ABC):
## ##
@property @property
def theResult(self) -> str: def result(self) -> str:
"""The result of the build process.""" """The result of the build process."""
return self._result return self._result
@property @property
def theMarkdown(self) -> list: def allMarkdown(self) -> list:
"""The combined novelWriter Markdown text.""" """The combined novelWriter Markdown text."""
return self._allMarkdown return self._allMarkdown
@@ -358,8 +358,8 @@ class Tokenizer(ABC):
return True return True
def setText(self, tHandle: str, text: str | None = None) -> bool: def setText(self, tHandle: str, text: str | None = None) -> bool:
"""Set the text for the tokenizer from a handle. If theText is """Set the text for the tokenizer from a handle. If text is not
not set, load it from the file. set, load it from the file.
""" """
self._nwItem = self._project.tree[tHandle] self._nwItem = self._project.tree[tHandle]
if self._nwItem is None: if self._nwItem is None:
+4 -4
View File
@@ -682,12 +682,12 @@ class ToOdt(Tokenizer):
return parName return parName
oStyle.setParentStyleName(parName) oStyle.setParentStyleName(parName)
theID = oStyle.getID() pID = oStyle.getID()
if theID in self._autoPara: if pID in self._autoPara:
return self._autoPara[theID][0] return self._autoPara[pID][0]
newName = "P%d" % (len(self._autoPara) + 1) newName = "P%d" % (len(self._autoPara) + 1)
self._autoPara[theID] = (newName, oStyle) self._autoPara[pID] = (newName, oStyle)
return newName return newName
+1 -1
View File
@@ -500,7 +500,7 @@ class NWTree:
## ##
def _setTreeChanged(self, state: bool) -> None: def _setTreeChanged(self, state: bool) -> None:
"""Set the changed flag to theState, and if being set to True, """Set the changed flag to state, and if being set to True,
propagate that state change to the parent NWProject class. propagate that state change to the parent NWProject class.
""" """
self._changed = state self._changed = state
+3 -3
View File
@@ -77,9 +77,9 @@ class GuiQuoteSelect(QDialog):
minSize = 100 minSize = 100
for sKey, sLabel in nwQuotes.SYMBOLS.items(): for sKey, sLabel in nwQuotes.SYMBOLS.items():
theText = "[ %s ] %s" % (sKey, trConst(sLabel)) text = "[ %s ] %s" % (sKey, trConst(sLabel))
minSize = max(minSize, qMetrics.boundingRect(theText).width()) minSize = max(minSize, qMetrics.boundingRect(text).width())
qtItem = QListWidgetItem(theText) qtItem = QListWidgetItem(text)
qtItem.setData(self.D_KEY, sKey) qtItem.setData(self.D_KEY, sKey)
self.listBox.addItem(qtItem) self.listBox.addItem(qtItem)
if sKey == current: if sKey == current:
+3 -3
View File
@@ -256,9 +256,9 @@ class GuiDocHighlighter(QSyntaxHighlighter):
nBlocks = qDoc.blockCount() nBlocks = qDoc.blockCount()
tStart = time() tStart = time()
for i in range(nBlocks): for i in range(nBlocks):
theBlock = qDoc.findBlockByNumber(i) block = qDoc.findBlockByNumber(i)
if theBlock.userState() & cType > 0: if block.userState() & cType > 0:
self.rehighlightBlock(theBlock) self.rehighlightBlock(block)
logger.debug("Document highlighted in %.3f ms" % (1000*(time() - tStart))) logger.debug("Document highlighted in %.3f ms" % (1000*(time() - tStart)))
return return
+4 -4
View File
@@ -229,7 +229,7 @@ class GuiDocViewer(QTextBrowser):
self.setDocumentTitle(tHandle) self.setDocumentTitle(tHandle)
# Replace tabs before setting the HTML, and then put them back in # Replace tabs before setting the HTML, and then put them back in
self.setHtml(aDoc.theResult.replace("\t", "!!tab!!")) self.setHtml(aDoc.result.replace("\t", "!!tab!!"))
while self.find("!!tab!!"): while self.find("!!tab!!"):
self.textCursor().insertText("\t") self.textCursor().insertText("\t")
@@ -367,9 +367,9 @@ class GuiDocViewer(QTextBrowser):
link = url.url() link = url.url()
logger.debug("Clicked link: '%s'", link) logger.debug("Clicked link: '%s'", link)
if len(link) > 0: if len(link) > 0:
theBits = link.split("=") bits = link.split("=")
if len(theBits) == 2: if len(bits) == 2:
self.loadDocumentTagRequest.emit(theBits[1], nwDocMode.VIEW) self.loadDocumentTagRequest.emit(bits[1], nwDocMode.VIEW)
return return
@pyqtSlot("QPoint") @pyqtSlot("QPoint")
+7 -7
View File
@@ -239,9 +239,9 @@ class GuiItemDetails(QWidget):
# Label # Label
# ===== # =====
theLabel = nwItem.itemName label = nwItem.itemName
if len(theLabel) > 100: if len(label) > 100:
theLabel = theLabel[:96].rstrip()+" ..." label = label[:96].rstrip()+" ..."
if nwItem.isFileType(): if nwItem.isFileType():
if nwItem.isActive: if nwItem.isActive:
@@ -251,14 +251,14 @@ class GuiItemDetails(QWidget):
else: else:
self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx))) self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx)))
self.labelData.setText(theLabel) self.labelData.setText(label)
# Status # Status
# ====== # ======
theStatus, theIcon = nwItem.getImportStatus(incIcon=True) status, icon = nwItem.getImportStatus(incIcon=True)
self.statusIcon.setPixmap(theIcon.pixmap(iPx, iPx)) self.statusIcon.setPixmap(icon.pixmap(iPx, iPx))
self.statusData.setText(theStatus) self.statusData.setText(status)
# Class # Class
# ===== # =====
+4 -4
View File
@@ -726,17 +726,17 @@ class GuiNovelTree(QTreeWidget):
refData = [] refData = []
refName = "" refName = ""
theRefs = SHARED.project.index.getReferences(tHandle, sTitle) refs = SHARED.project.index.getReferences(tHandle, sTitle)
if self._lastCol == NovelTreeColumn.POV: if self._lastCol == NovelTreeColumn.POV:
refData = theRefs[nwKeyWords.POV_KEY] refData = refs[nwKeyWords.POV_KEY]
refName = self._povLabel refName = self._povLabel
elif self._lastCol == NovelTreeColumn.FOCUS: elif self._lastCol == NovelTreeColumn.FOCUS:
refData = theRefs[nwKeyWords.FOCUS_KEY] refData = refs[nwKeyWords.FOCUS_KEY]
refName = self._focLabel refName = self._focLabel
elif self._lastCol == NovelTreeColumn.PLOT: elif self._lastCol == NovelTreeColumn.PLOT:
refData = theRefs[nwKeyWords.PLOT_KEY] refData = refs[nwKeyWords.PLOT_KEY]
refName = self._pltLabel refName = self._pltLabel
if refData: if refData:
+13 -13
View File
@@ -625,12 +625,12 @@ class GuiOutlineTree(QTreeWidget):
self.clear() self.clear()
if self._firstView: if self._firstView:
theLabels = [] labels = []
for i, hItem in enumerate(self._treeOrder): for i, hItem in enumerate(self._treeOrder):
theLabels.append(trConst(nwLabels.OUTLINE_COLS[hItem])) labels.append(trConst(nwLabels.OUTLINE_COLS[hItem]))
self._colIdx[hItem] = i self._colIdx[hItem] = i
self.setHeaderLabels(theLabels) self.setHeaderLabels(labels)
for hItem in self._treeOrder: for hItem in self._treeOrder:
self.setColumnWidth(self._colIdx[hItem], self._colWidth[hItem]) self.setColumnWidth(self._colIdx[hItem], self._colWidth[hItem])
self.setColumnHidden(self._colIdx[hItem], self._colHidden[hItem]) self.setColumnHidden(self._colIdx[hItem], self._colHidden[hItem])
@@ -990,7 +990,7 @@ class GuiOutlineDetails(QScrollArea):
pIndex = SHARED.project.index pIndex = SHARED.project.index
nwItem = SHARED.project.tree[tHandle] nwItem = SHARED.project.tree[tHandle]
novIdx = pIndex.getItemHeader(tHandle, sTitle) novIdx = pIndex.getItemHeader(tHandle, sTitle)
theRefs = pIndex.getReferences(tHandle, sTitle) novRefs = pIndex.getReferences(tHandle, sTitle)
if nwItem is None or novIdx is None: if nwItem is None or novIdx is None:
return False return False
@@ -1015,15 +1015,15 @@ class GuiOutlineDetails(QScrollArea):
self.synopValue.setText(novIdx.synopsis) self.synopValue.setText(novIdx.synopsis)
self.povKeyValue.setText(self._formatTags(theRefs, nwKeyWords.POV_KEY)) self.povKeyValue.setText(self._formatTags(novRefs, nwKeyWords.POV_KEY))
self.focKeyValue.setText(self._formatTags(theRefs, nwKeyWords.FOCUS_KEY)) self.focKeyValue.setText(self._formatTags(novRefs, nwKeyWords.FOCUS_KEY))
self.chrKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CHAR_KEY)) self.chrKeyValue.setText(self._formatTags(novRefs, nwKeyWords.CHAR_KEY))
self.pltKeyValue.setText(self._formatTags(theRefs, nwKeyWords.PLOT_KEY)) self.pltKeyValue.setText(self._formatTags(novRefs, nwKeyWords.PLOT_KEY))
self.timKeyValue.setText(self._formatTags(theRefs, nwKeyWords.TIME_KEY)) self.timKeyValue.setText(self._formatTags(novRefs, nwKeyWords.TIME_KEY))
self.wldKeyValue.setText(self._formatTags(theRefs, nwKeyWords.WORLD_KEY)) self.wldKeyValue.setText(self._formatTags(novRefs, nwKeyWords.WORLD_KEY))
self.objKeyValue.setText(self._formatTags(theRefs, nwKeyWords.OBJECT_KEY)) self.objKeyValue.setText(self._formatTags(novRefs, nwKeyWords.OBJECT_KEY))
self.entKeyValue.setText(self._formatTags(theRefs, nwKeyWords.ENTITY_KEY)) self.entKeyValue.setText(self._formatTags(novRefs, nwKeyWords.ENTITY_KEY))
self.cstKeyValue.setText(self._formatTags(theRefs, nwKeyWords.CUSTOM_KEY)) self.cstKeyValue.setText(self._formatTags(novRefs, nwKeyWords.CUSTOM_KEY))
return True return True
+12 -12
View File
@@ -785,24 +785,24 @@ class GuiProjectTree(QTreeWidget):
project structure, and must be called before any code that project structure, and must be called before any code that
depends on this order to be up to date. depends on this order to be up to date.
""" """
theList = [] items = []
for i in range(self.topLevelItemCount()): for i in range(self.topLevelItemCount()):
item = self.topLevelItem(i) item = self.topLevelItem(i)
if isinstance(item, QTreeWidgetItem): if isinstance(item, QTreeWidgetItem):
theList = self._scanChildren(theList, item, i) items = self._scanChildren(items, item, i)
logger.debug("Saving project tree item order") logger.debug("Saving project tree item order")
SHARED.project.setTreeOrder(theList) SHARED.project.setTreeOrder(items)
return return
def getTreeFromHandle(self, tHandle: str) -> list[str]: def getTreeFromHandle(self, tHandle: str) -> list[str]:
"""Recursively return all the child items starting from a given """Recursively return all the child items starting from a given
item handle. item handle.
""" """
theList = [] result = []
theItem = self._getTreeItem(tHandle) tIten = self._getTreeItem(tHandle)
if theItem is not None: if tIten is not None:
theList = self._scanChildren(theList, theItem, 0) result = self._scanChildren(result, tIten, 0)
return theList return result
def requestDeleteItem(self, tHandle: str | None = None) -> bool: def requestDeleteItem(self, tHandle: str | None = None) -> bool:
"""Request an item deleted from the project tree. This function """Request an item deleted from the project tree. This function
@@ -857,11 +857,11 @@ class GuiProjectTree(QTreeWidget):
SHARED.info(self.tr("There is currently no Trash folder in this project.")) SHARED.info(self.tr("There is currently no Trash folder in this project."))
return False return False
theTrash = self.getTreeFromHandle(trashHandle) trashItems = self.getTreeFromHandle(trashHandle)
if trashHandle in theTrash: if trashHandle in trashItems:
theTrash.remove(trashHandle) trashItems.remove(trashHandle)
nTrash = len(theTrash) nTrash = len(trashItems)
if nTrash == 0: if nTrash == 0:
SHARED.info(self.tr("The Trash folder is already empty.")) SHARED.info(self.tr("The Trash folder is already empty."))
return False return False
+9 -9
View File
@@ -368,22 +368,22 @@ class GuiTheme:
def _setGuiFont(self) -> None: def _setGuiFont(self) -> None:
"""Update the GUI's font style from settings.""" """Update the GUI's font style from settings."""
theFont = QFont() font = QFont()
fontDB = QFontDatabase() fontDB = QFontDatabase()
if CONFIG.guiFont not in fontDB.families(): if CONFIG.guiFont not in fontDB.families():
if CONFIG.osWindows and "Arial" in fontDB.families(): if CONFIG.osWindows and "Arial" in fontDB.families():
# On Windows we default to Arial if possible # On Windows we default to Arial if possible
theFont.setFamily("Arial") font.setFamily("Arial")
theFont.setPointSize(10) font.setPointSize(10)
else: else:
theFont = fontDB.systemFont(QFontDatabase.GeneralFont) font = fontDB.systemFont(QFontDatabase.GeneralFont)
CONFIG.guiFont = theFont.family() CONFIG.guiFont = font.family()
CONFIG.guiFontSize = theFont.pointSize() CONFIG.guiFontSize = font.pointSize()
else: else:
theFont.setFamily(CONFIG.guiFont) font.setFamily(CONFIG.guiFont)
theFont.setPointSize(CONFIG.guiFontSize) font.setPointSize(CONFIG.guiFontSize)
qApp.setFont(theFont) qApp.setFont(font)
return return
+3 -3
View File
@@ -679,10 +679,10 @@ class GuiMain(QMainWindow):
if loadFile.strip() == "": if loadFile.strip() == "":
return False return False
theText = None text = None
try: try:
with open(loadFile, mode="rt", encoding="utf-8") as inFile: with open(loadFile, mode="rt", encoding="utf-8") as inFile:
theText = inFile.read() text = inFile.read()
CONFIG.setLastPath(loadFile) CONFIG.setLastPath(loadFile)
except Exception as exc: except Exception as exc:
SHARED.error(self.tr( SHARED.error(self.tr(
@@ -704,7 +704,7 @@ class GuiMain(QMainWindow):
if not msgYes: if not msgYes:
return False return False
self.docEditor.replaceText(theText) self.docEditor.replaceText(text)
return True return True
+5 -5
View File
@@ -375,9 +375,9 @@ class GuiManuscript(QDialog):
@pyqtSlot() @pyqtSlot()
def _printDocument(self) -> None: def _printDocument(self) -> None:
"""Open the print preview dialog.""" """Open the print preview dialog."""
thePreview = QPrintPreviewDialog(self) preview = QPrintPreviewDialog(self)
thePreview.paintRequested.connect(self.docPreview.printPreview) preview.paintRequested.connect(self.docPreview.printPreview)
thePreview.exec_() preview.exec_()
return return
## ##
@@ -771,8 +771,8 @@ class _PreviewWidget(QTextBrowser):
self.setHtml(html) self.setHtml(html)
qApp.processEvents() qApp.processEvents()
while self.find("!!tab!!"): while self.find("!!tab!!"):
theCursor = self.textCursor() cursor = self.textCursor()
theCursor.insertText("\t") cursor.insertText("\t")
self.verticalScrollBar().setValue(sPos) self.verticalScrollBar().setValue(sPos)
self._docTime = checkInt(data.get("time"), 0) self._docTime = checkInt(data.get("time"), 0)
+4 -4
View File
@@ -1112,10 +1112,10 @@ class _FormatTab(NScrollableForm):
currFont = QFont() currFont = QFont()
currFont.setFamily(self.textFont.text()) currFont.setFamily(self.textFont.text())
currFont.setPointSize(self.textSize.value()) currFont.setPointSize(self.textSize.value())
theFont, theStatus = QFontDialog.getFont(currFont, self) newFont, status = QFontDialog.getFont(currFont, self)
if theStatus: if status:
self.textFont.setText(theFont.family()) self.textFont.setText(newFont.family())
self.textSize.setValue(theFont.pointSize()) self.textSize.setValue(newFont.pointSize())
return return
@pyqtSlot(int) @pyqtSlot(int)
+3 -3
View File
@@ -455,19 +455,19 @@ class _ContentsPage(NFixedPage):
pTotal = 0 pTotal = 0
tPages = 1 tPages = 1
theList = [] entries = []
for _, tLevel, tTitle, wCount in self._data: for _, tLevel, tTitle, wCount in self._data:
pCount = math.ceil(wCount/wpPage) pCount = math.ceil(wCount/wpPage)
if dblPages: if dblPages:
pCount += pCount%2 pCount += pCount%2
pTotal += pCount pTotal += pCount
theList.append((tLevel, tTitle, wCount, pCount)) entries.append((tLevel, tTitle, wCount, pCount))
pMax = pTotal - fstPage pMax = pTotal - fstPage
self.tocTree.clear() self.tocTree.clear()
for tLevel, tTitle, wCount, pCount in theList: for tLevel, tTitle, wCount, pCount in entries:
newItem = QTreeWidgetItem() newItem = QTreeWidgetItem()
if tPages <= fstPage: if tPages <= fstPage:
+2 -2
View File
@@ -585,13 +585,13 @@ class GuiWritingStats(QDialog):
newItem.setText(self.C_COUNT, f"{nWords:n}") newItem.setText(self.C_COUNT, f"{nWords:n}")
if nWords > 0 and listMax > 0: if nWords > 0 and listMax > 0:
theBar = self.barImage.scaled( wBar = self.barImage.scaled(
int(200*min(nWords, histMax)/listMax), int(200*min(nWords, histMax)/listMax),
self.barHeight, self.barHeight,
Qt.IgnoreAspectRatio, Qt.IgnoreAspectRatio,
Qt.FastTransformation Qt.FastTransformation
) )
newItem.setData(self.C_BAR, Qt.DecorationRole, theBar) newItem.setData(self.C_BAR, Qt.DecorationRole, wBar)
newItem.setTextAlignment(self.C_LENGTH, Qt.AlignRight) newItem.setTextAlignment(self.C_LENGTH, Qt.AlignRight)
newItem.setTextAlignment(self.C_IDLE, Qt.AlignRight) newItem.setTextAlignment(self.C_IDLE, Qt.AlignRight)
+5 -5
View File
@@ -47,9 +47,9 @@ def extractVersion(beQuiet: bool = False) -> tuple[str, str, str]:
"""Extract the novelWriter version number without having to import """Extract the novelWriter version number without having to import
anything else from the main package. anything else from the main package.
""" """
def getValue(theString): def getValue(text):
theBits = theString.partition("=") bits = text.partition("=")
return theBits[2].strip().strip('"') return bits[2].strip().strip('"')
numVers = "0" numVers = "0"
hexVers = "0x0" hexVers = "0x0"
@@ -1744,7 +1744,7 @@ def winUninstall() -> None:
print("") print("")
print("Removing registry keys ...") print("Removing registry keys ...")
theKeys = [ keys = [
r"Software\Classes\novelWriterProject.nwx\shell\open\command", r"Software\Classes\novelWriterProject.nwx\shell\open\command",
r"Software\Classes\novelWriterProject.nwx\shell\open", r"Software\Classes\novelWriterProject.nwx\shell\open",
r"Software\Classes\novelWriterProject.nwx\shell", r"Software\Classes\novelWriterProject.nwx\shell",
@@ -1756,7 +1756,7 @@ def winUninstall() -> None:
r"Software\Classes\Applications\novelWriter.pyw", r"Software\Classes\Applications\novelWriter.pyw",
] ]
for aKey in theKeys: for aKey in keys:
try: try:
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, aKey) winreg.DeleteKey(winreg.HKEY_CURRENT_USER, aKey)
print("Deleted: HKEY_CURRENT_USER\\%s" % aKey) print("Deleted: HKEY_CURRENT_USER\\%s" % aKey)
+4 -4
View File
@@ -39,7 +39,7 @@ class MockGuiMain(QWidget):
def postLaunchTasks(self, cmdOpen): def postLaunchTasks(self, cmdOpen):
return return
def setStatus(self, theMessage): def setStatus(self, message):
return return
def openProject(self, projPath): def openProject(self, projPath):
@@ -63,10 +63,10 @@ class MockStatusBar:
def __init__(self): def __init__(self):
return return
def setStatus(self, theText): def setStatus(self, text):
return return
def updateProjectStatus(self, theStatus): def updateProjectStatus(self, status):
return return
# END Class MockStatusBar # END Class MockStatusBar
@@ -89,7 +89,7 @@ class MockApp:
def __init__(self): def __init__(self):
return return
def installTranslator(self, theLang): def installTranslator(self, language):
return return
# END Class MockApp # END Class MockApp
+8 -8
View File
@@ -177,19 +177,19 @@ def testBaseConfig_Localisation(fncPath, tstPaths):
tstConf.initLocalisation(tstApp) # type: ignore tstConf.initLocalisation(tstApp) # type: ignore
# Check Lists # Check Lists
theList = tstConf.listLanguages(tstConf.LANG_NW) languages = tstConf.listLanguages(tstConf.LANG_NW)
assert theList == [("en_GB", "British English")] assert languages == [("en_GB", "British English")]
theList = tstConf.listLanguages(tstConf.LANG_PROJ) languages = tstConf.listLanguages(tstConf.LANG_PROJ)
assert theList == [("en_GB", "British English")] assert languages == [("en_GB", "British English")]
theList = tstConf.listLanguages(None) # type: ignore languages = tstConf.listLanguages(None) # type: ignore
assert theList == [] assert languages == []
# Add Language # Add Language
copyfile(tstPaths.filesDir / "nw_en_GB.qm", i18nDir / "nw_fr.qm") copyfile(tstPaths.filesDir / "nw_en_GB.qm", i18nDir / "nw_fr.qm")
writeFile(i18nDir / "nw_fr.ts", "") writeFile(i18nDir / "nw_fr.ts", "")
theList = tstConf.listLanguages(tstConf.LANG_NW) languages = tstConf.listLanguages(tstConf.LANG_NW)
assert theList == [("en_GB", "British English"), ("fr", "Français")] assert languages == [("en_GB", "British English"), ("fr", "Français")]
# END Test testBaseConfig_Localisation # END Test testBaseConfig_Localisation
+8 -8
View File
@@ -43,19 +43,19 @@ def testBaseError_Dialog(qtbot, monkeypatch, nwGUI):
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", lambda: "1.2.3") mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", lambda: "1.2.3")
nwErr.setMessage(Exception, "Fine Error", None) nwErr.setMessage(Exception, "Fine Error", None)
theMessage = nwErr.msgBody.toPlainText() message = nwErr.msgBody.toPlainText()
assert theMessage != "" assert message != ""
assert "Fine Error" in theMessage assert "Fine Error" in message
assert "Exception" in theMessage assert "Exception" in message
assert "(1.2.3)" in theMessage assert "(1.2.3)" in message
# No kernel version retrieved # No kernel version retrieved
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", causeException) mp.setattr("PyQt5.QtCore.QSysInfo.kernelVersion", causeException)
nwErr.setMessage(Exception, "Almost Fine Error", None) nwErr.setMessage(Exception, "Almost Fine Error", None)
theMessage = nwErr.msgBody.toPlainText() message = nwErr.msgBody.toPlainText()
assert theMessage != "" assert message != ""
assert "(Unknown)" in theMessage assert "(Unknown)" in message
nwErr._doClose() nwErr._doClose()
nwErr.close() nwErr.close()
+70 -70
View File
@@ -35,51 +35,51 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test loading and saving a document with the NWDocument class.""" """Test loading and saving a document with the NWDocument class."""
monkeypatch.setattr("novelwriter.core.document.time", lambda: MOCK_TIME) monkeypatch.setattr("novelwriter.core.document.time", lambda: MOCK_TIME)
theProject = NWProject() project = NWProject()
mockRnd.reset() mockRnd.reset()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
# Read Document # Read Document
# ============= # =============
# Not a valid handle # Not a valid handle
theDoc = NWDocument(theProject, "stuff") doc = NWDocument(project, "stuff")
assert bool(theDoc) is False assert bool(doc) is False
assert theDoc.readDocument() is None assert doc.readDocument() is None
assert theDoc.fileExists() is False assert doc.fileExists() is False
# Non-existent handle # Non-existent handle
theDoc = NWDocument(theProject, C.hInvalid) doc = NWDocument(project, C.hInvalid)
assert theDoc.readDocument() is None assert doc.readDocument() is None
assert theDoc._lastHash == "" assert doc._lastHash == ""
assert theDoc.fileExists() is False assert doc.fileExists() is False
# No content path # No content path
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None)) mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, C.hSceneDoc) doc = NWDocument(project, C.hSceneDoc)
assert theDoc.readDocument() is None assert doc.readDocument() is None
assert theDoc.fileExists() is False assert doc.fileExists() is False
# Cause open() to fail while loading # Cause open() to fail while loading
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
theDoc = NWDocument(theProject, C.hSceneDoc) doc = NWDocument(project, C.hSceneDoc)
assert theDoc.fileExists() is True assert doc.fileExists() is True
assert theDoc.readDocument() is None assert doc.readDocument() is None
assert theDoc.getError() == "OSError: Mock OSError" assert doc.getError() == "OSError: Mock OSError"
# Load the text # Load the text
theDoc = NWDocument(theProject, C.hSceneDoc) doc = NWDocument(project, C.hSceneDoc)
assert theDoc.fileExists() is True assert doc.fileExists() is True
assert theDoc.readDocument() == "### New Scene\n\n" assert doc.readDocument() == "### New Scene\n\n"
# Try to open a new (non-existent) file # Try to open a new (non-existent) file
xHandle = theProject.newFile("New File", C.hNovelRoot) xHandle = project.newFile("New File", C.hNovelRoot)
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert bool(theDoc) is True assert bool(doc) is True
assert repr(theDoc) == f"<NWDocument handle={xHandle}>" assert repr(doc) == f"<NWDocument handle={xHandle}>"
assert theDoc.readDocument() == "" assert doc.readDocument() == ""
# Write Document # Write Document
# ============== # ==============
@@ -87,17 +87,17 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
# No content path # No content path
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None)) mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert theDoc.writeDocument("") is False assert doc.writeDocument("") is False
# Set handle and save # Set handle and save
theText = "### Test File\n\nText ...\n\n" text = "### Test File\n\nText ...\n\n"
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert theDoc.readDocument(xHandle) == "" # type: ignore assert doc.readDocument(xHandle) == "" # type: ignore
assert theDoc.writeDocument(theText) 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
assert theDoc.writeDocument(theText) is True assert doc.writeDocument(text) is True
# Check file content # Check file content
docPath = fncPath / "content" / f"{xHandle}.nwd" docPath = fncPath / "content" / f"{xHandle}.nwd"
@@ -113,62 +113,62 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncPath, mockRnd):
# Alter the document on disk and save again # Alter the document on disk and save again
writeFile(docPath, "blablabla") writeFile(docPath, "blablabla")
assert theDoc.writeDocument(theText) is False assert doc.writeDocument(text) is False
# Force the overwrite # Force the overwrite
assert theDoc.writeDocument(theText, forceWrite=True) is True assert doc.writeDocument(text, forceWrite=True) is True
# Force no meta data # Force no meta data
theDoc._item = None doc._item = None
assert theDoc.writeDocument(theText) is True assert doc.writeDocument(text) is True
assert readFile(docPath) == theText assert readFile(docPath) == text
# Cause open() to fail while saving # Cause open() to fail while saving
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert theDoc.writeDocument(theText) is False assert doc.writeDocument(text) is False
assert theDoc.getError() == "OSError: Mock OSError" assert doc.getError() == "OSError: Mock OSError"
theDoc._docError = "" doc._docError = ""
assert theDoc.getError() == "" assert doc.getError() == ""
# Cause os.replace() to fail while saving # Cause os.replace() to fail while saving
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("pathlib.Path.replace", causeOSError) mp.setattr("pathlib.Path.replace", causeOSError)
assert theDoc.writeDocument(theText) is False assert doc.writeDocument(text) is False
assert theDoc.getError() == "OSError: Mock OSError" assert doc.getError() == "OSError: Mock OSError"
theDoc._docError = "" doc._docError = ""
assert theDoc.getError() == "" assert doc.getError() == ""
# Saving with no handle # Saving with no handle
theDoc._handle = None doc._handle = None
assert theDoc.writeDocument(theText) is False assert doc.writeDocument(text) is False
# Delete Document # Delete Document
# =============== # ===============
# Delete a non-existing document # Delete a non-existing document
theDoc = NWDocument(theProject, "stuff") doc = NWDocument(project, "stuff")
assert theDoc.deleteDocument() is False assert doc.deleteDocument() is False
assert docPath.exists() assert docPath.exists()
# No content path # No content path
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None)) mp.setattr("novelwriter.core.storage.NWStorage.contentPath", property(lambda *a: None))
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert theDoc.deleteDocument() is False assert doc.deleteDocument() is False
# Cause the delete to fail # Cause the delete to fail
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("pathlib.Path.unlink", causeOSError) mp.setattr("pathlib.Path.unlink", causeOSError)
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert theDoc.deleteDocument() is False assert doc.deleteDocument() is False
assert theDoc.getError() == "OSError: Mock OSError" assert doc.getError() == "OSError: Mock OSError"
# Make the delete pass # Make the delete pass
theDoc = NWDocument(theProject, xHandle) doc = NWDocument(project, xHandle)
assert theDoc.deleteDocument() is True assert doc.deleteDocument() is True
assert not docPath.exists() assert not docPath.exists()
# END Test testCoreDocument_Load # END Test testCoreDocument_Load
@@ -179,31 +179,31 @@ def testCoreDocument_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test other methods of the NWDocument class.""" """Test other methods of the NWDocument class."""
monkeypatch.setattr("novelwriter.core.document.time", lambda: MOCK_TIME) monkeypatch.setattr("novelwriter.core.document.time", lambda: MOCK_TIME)
theProject = NWProject() project = NWProject()
mockRnd.reset() mockRnd.reset()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
theDoc = NWDocument(theProject, C.hSceneDoc) doc = NWDocument(project, C.hSceneDoc)
docPath = fncPath / "content" / f"{C.hSceneDoc}.nwd" docPath = fncPath / "content" / f"{C.hSceneDoc}.nwd"
assert theDoc.readDocument() == "### New Scene\n\n" assert doc.readDocument() == "### New Scene\n\n"
# Check location # Check location
assert theDoc.fileLocation == str(docPath) assert doc.fileLocation == str(docPath)
# Check the item # Check the item
assert theDoc.nwItem is not None assert doc.nwItem is not None
assert theDoc.nwItem.itemHandle == C.hSceneDoc # type: ignore assert doc.nwItem.itemHandle == C.hSceneDoc # type: ignore
# Check the meta # Check the meta
theName, theParent, theClass, theLayout = theDoc.getMeta() name, parent, itemClass, itemLayout = doc.getMeta()
assert theName == "New Scene" assert name == "New Scene"
assert theParent == C.hChapterDir assert parent == C.hChapterDir
assert theClass == nwItemClass.NOVEL assert itemClass == nwItemClass.NOVEL
assert theLayout == nwItemLayout.DOCUMENT assert itemLayout == nwItemLayout.DOCUMENT
# Add meta data garbage # Add meta data garbage
assert theDoc.writeDocument("%%~ stuff\n### Test File\n\nText ...\n\n") assert doc.writeDocument("%%~ stuff\n### Test File\n\nText ...\n\n")
assert readFile(docPath) == ( assert readFile(docPath) == (
"%%~name: New Scene\n" "%%~name: New Scene\n"
f"%%~path: {C.hChapterDir}/{C.hSceneDoc}\n" f"%%~path: {C.hChapterDir}/{C.hSceneDoc}\n"
@@ -215,6 +215,6 @@ def testCoreDocument_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"Text ...\n\n" "Text ...\n\n"
) )
assert theDoc.readDocument() == "### Test File\n\nText ...\n\n" assert doc.readDocument() == "### Test File\n\nText ...\n\n"
# END Test testCoreDocument_Methods # END Test testCoreDocument_Methods
+25 -25
View File
@@ -160,52 +160,52 @@ def testCoreIndex_ScanThis(mockGUI):
project = NWProject() project = NWProject()
index = project.index index = project.index
isValid, theBits, thePos = index.scanThis("tag: this, and this") isValid, bits, pos = index.scanThis("tag: this, and this")
assert isValid is False assert isValid is False
isValid, theBits, thePos = index.scanThis("@") isValid, bits, pos = index.scanThis("@")
assert isValid is False assert isValid is False
isValid, theBits, thePos = index.scanThis("@:") isValid, bits, pos = index.scanThis("@:")
assert isValid is False assert isValid is False
isValid, theBits, thePos = index.scanThis(" @a: b") isValid, bits, pos = index.scanThis(" @a: b")
assert isValid is False assert isValid is False
isValid, theBits, thePos = index.scanThis("@a:") isValid, bits, pos = index.scanThis("@a:")
assert isValid is True assert isValid is True
assert theBits == ["@a"] assert bits == ["@a"]
assert thePos == [0] assert pos == [0]
isValid, theBits, thePos = index.scanThis("@a:b") isValid, bits, pos = index.scanThis("@a:b")
assert isValid is True assert isValid is True
assert theBits == ["@a", "b"] assert bits == ["@a", "b"]
assert thePos == [0, 3] assert pos == [0, 3]
isValid, theBits, thePos = index.scanThis("@a:b,c,d") isValid, bits, pos = index.scanThis("@a:b,c,d")
assert isValid is True assert isValid is True
assert theBits == ["@a", "b", "c", "d"] assert bits == ["@a", "b", "c", "d"]
assert thePos == [0, 3, 5, 7] assert pos == [0, 3, 5, 7]
isValid, theBits, thePos = index.scanThis("@a : b , c , d") isValid, bits, pos = index.scanThis("@a : b , c , d")
assert isValid is True assert isValid is True
assert theBits == ["@a", "b", "c", "d"] assert bits == ["@a", "b", "c", "d"]
assert thePos == [0, 5, 9, 13] assert pos == [0, 5, 9, 13]
isValid, theBits, thePos = index.scanThis("@tag: this, and this") isValid, bits, pos = index.scanThis("@tag: this, and this")
assert isValid is True assert isValid is True
assert theBits == ["@tag", "this", "and this"] assert bits == ["@tag", "this", "and this"]
assert thePos == [0, 6, 12] assert pos == [0, 6, 12]
isValid, theBits, thePos = index.scanThis("@tag: this,, and this") isValid, bits, pos = index.scanThis("@tag: this,, and this")
assert isValid is True assert isValid is True
assert theBits == ["@tag", "this", "", "and this"] assert bits == ["@tag", "this", "", "and this"]
assert thePos == [0, 6, 11, 13] assert pos == [0, 6, 11, 13]
isValid, theBits, thePos = index.scanThis("@tag: this, , and this") isValid, bits, pos = index.scanThis("@tag: this, , and this")
assert isValid is True assert isValid is True
assert theBits == ["@tag", "this", "", "and this"] assert bits == ["@tag", "this", "", "and this"]
assert thePos == [0, 6, 12, 14] assert pos == [0, 6, 12, 14]
project.closeProject() project.closeProject()
+349 -349
View File
@@ -35,150 +35,150 @@ from novelwriter.core.project import NWProject
@pytest.mark.core @pytest.mark.core
def testCoreItem_Setters(mockGUI, mockRnd, fncPath): def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
"""Test all the simple setters for the NWItem class.""" """Test all the simple setters for the NWItem class."""
theProject = NWProject() project = NWProject()
mockRnd.reset() mockRnd.reset()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
assert theItem.itemHandle == "0000000000000" assert item.itemHandle == "0000000000000"
statusKeys = ["s000000", "s000001", "s000002", "s000003"] statusKeys = ["s000000", "s000001", "s000002", "s000003"]
importKeys = ["i000004", "i000005", "i000006", "i000007"] importKeys = ["i000004", "i000005", "i000006", "i000007"]
# Name # Name
theItem.setName("A Name") item.setName("A Name")
assert theItem.itemName == "A Name" assert item.itemName == "A Name"
theItem.setName("\t A Name ") item.setName("\t A Name ")
assert theItem.itemName == "A Name" assert item.itemName == "A Name"
theItem.setName("\t A\t\u2009\u202f\u2002\u2003\u2028\u2029Name ") item.setName("\t A\t\u2009\u202f\u2002\u2003\u2028\u2029Name ")
assert theItem.itemName == "A Name" assert item.itemName == "A Name"
theItem.setName(123) item.setName(123)
assert theItem.itemName == "" assert item.itemName == ""
# Parent # Parent
theItem.setParent(None) item.setParent(None)
assert theItem.itemParent is None assert item.itemParent is None
theItem.setParent(123) item.setParent(123)
assert theItem.itemParent is None assert item.itemParent is None
theItem.setParent("0123456789abcdef") item.setParent("0123456789abcdef")
assert theItem.itemParent is None assert item.itemParent is None
theItem.setParent("0123456789abg") item.setParent("0123456789abg")
assert theItem.itemParent is None assert item.itemParent is None
theItem.setParent("0123456789abc") item.setParent("0123456789abc")
assert theItem.itemParent == "0123456789abc" assert item.itemParent == "0123456789abc"
# Root # Root
theItem.setRoot(None) item.setRoot(None)
assert theItem.itemRoot is None assert item.itemRoot is None
theItem.setRoot(123) item.setRoot(123)
assert theItem.itemRoot is None assert item.itemRoot is None
theItem.setRoot("0123456789abcdef") item.setRoot("0123456789abcdef")
assert theItem.itemRoot is None assert item.itemRoot is None
theItem.setRoot("0123456789abg") item.setRoot("0123456789abg")
assert theItem.itemRoot is None assert item.itemRoot is None
theItem.setRoot("0123456789abc") item.setRoot("0123456789abc")
assert theItem.itemRoot == "0123456789abc" assert item.itemRoot == "0123456789abc"
# Order # Order
theItem.setOrder(None) item.setOrder(None)
assert theItem.itemOrder == 0 assert item.itemOrder == 0
theItem.setOrder("1") item.setOrder("1")
assert theItem.itemOrder == 1 assert item.itemOrder == 1
theItem.setOrder(1) item.setOrder(1)
assert theItem.itemOrder == 1 assert item.itemOrder == 1
# Importance # Importance
theItem._class = nwItemClass.CHARACTER item._class = nwItemClass.CHARACTER
theItem.setImport("Word") item.setImport("Word")
assert theItem.itemImport == importKeys[0] # Default assert item.itemImport == importKeys[0] # Default
for key in importKeys: for key in importKeys:
theItem.setImport(key) item.setImport(key)
assert theItem.itemImport == key assert item.itemImport == key
# Status # Status
theItem._class = nwItemClass.NOVEL item._class = nwItemClass.NOVEL
theItem.setStatus("Word") item.setStatus("Word")
assert theItem.itemStatus == statusKeys[0] # Default assert item.itemStatus == statusKeys[0] # Default
for key in statusKeys: for key in statusKeys:
theItem.setStatus(key) item.setStatus(key)
assert theItem.itemStatus == key assert item.itemStatus == key
# Status/Importance Wrapper # Status/Importance Wrapper
theItem._class = nwItemClass.CHARACTER item._class = nwItemClass.CHARACTER
for key in importKeys: for key in importKeys:
theItem.setImport(key) item.setImport(key)
assert theItem.itemImport == key assert item.itemImport == key
assert theItem.itemStatus == statusKeys[3] # Should not change assert item.itemStatus == statusKeys[3] # Should not change
theItem._class = nwItemClass.NOVEL item._class = nwItemClass.NOVEL
for key in statusKeys: for key in statusKeys:
theItem.setStatus(key) item.setStatus(key)
assert theItem.itemImport == importKeys[3] # Should not change assert item.itemImport == importKeys[3] # Should not change
assert theItem.itemStatus == key assert item.itemStatus == key
# Expanded # Expanded
theItem.setExpanded(8) item.setExpanded(8)
assert theItem.isExpanded is False assert item.isExpanded is False
theItem.setExpanded(None) item.setExpanded(None)
assert theItem.isExpanded is False assert item.isExpanded is False
theItem.setExpanded("None") item.setExpanded("None")
assert theItem.isExpanded is False assert item.isExpanded is False
theItem.setExpanded("What?") item.setExpanded("What?")
assert theItem.isExpanded is False assert item.isExpanded is False
theItem.setExpanded("True") item.setExpanded("True")
assert theItem.isExpanded is False assert item.isExpanded is False
theItem.setExpanded(True) item.setExpanded(True)
assert theItem.isExpanded is True assert item.isExpanded is True
# Active # Active
theItem.setActive(8) item.setActive(8)
assert theItem.isActive is False assert item.isActive is False
theItem.setActive(None) item.setActive(None)
assert theItem.isActive is False assert item.isActive is False
theItem.setActive("None") item.setActive("None")
assert theItem.isActive is False assert item.isActive is False
theItem.setActive("What?") item.setActive("What?")
assert theItem.isActive is False assert item.isActive is False
theItem.setActive("True") item.setActive("True")
assert theItem.isActive is False assert item.isActive is False
theItem.setActive(True) item.setActive(True)
assert theItem.isActive is True assert item.isActive is True
# CharCount # CharCount
theItem.setCharCount(None) item.setCharCount(None)
assert theItem.charCount == 0 assert item.charCount == 0
theItem.setCharCount("1") item.setCharCount("1")
assert theItem.charCount == 0 assert item.charCount == 0
theItem.setCharCount(1) item.setCharCount(1)
assert theItem.charCount == 1 assert item.charCount == 1
# WordCount # WordCount
theItem.setWordCount(None) item.setWordCount(None)
assert theItem.wordCount == 0 assert item.wordCount == 0
theItem.setWordCount("1") item.setWordCount("1")
assert theItem.wordCount == 0 assert item.wordCount == 0
theItem.setWordCount(1) item.setWordCount(1)
assert theItem.wordCount == 1 assert item.wordCount == 1
# ParaCount # ParaCount
theItem.setParaCount(None) item.setParaCount(None)
assert theItem.paraCount == 0 assert item.paraCount == 0
theItem.setParaCount("1") item.setParaCount("1")
assert theItem.paraCount == 0 assert item.paraCount == 0
theItem.setParaCount(1) item.setParaCount(1)
assert theItem.paraCount == 1 assert item.paraCount == 1
# CursorPos # CursorPos
theItem.setCursorPos(None) item.setCursorPos(None)
assert theItem.cursorPos == 0 assert item.cursorPos == 0
theItem.setCursorPos("1") item.setCursorPos("1")
assert theItem.cursorPos == 0 assert item.cursorPos == 0
theItem.setCursorPos(1) item.setCursorPos(1)
assert theItem.cursorPos == 1 assert item.cursorPos == 1
# Initial Count # Initial Count
theItem.setWordCount(234) item.setWordCount(234)
theItem.saveInitialCount() item.saveInitialCount()
assert theItem.initCount == 234 assert item.initCount == 234
# END Test testCoreItem_Setters # END Test testCoreItem_Setters
@@ -186,91 +186,91 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
@pytest.mark.core @pytest.mark.core
def testCoreItem_Methods(mockGUI, mockRnd, fncPath): def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
"""Test the simple methods of the NWItem class.""" """Test the simple methods of the NWItem class."""
theProject = NWProject() project = NWProject()
mockRnd.reset() mockRnd.reset()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
# Describe Me # Describe Me
# =========== # ===========
assert theItem.describeMe() == "None" assert item.describeMe() == "None"
theItem.setType("ROOT") item.setType("ROOT")
assert theItem.describeMe() == "Root Folder" assert item.describeMe() == "Root Folder"
assert theItem.isRootType() is True assert item.isRootType() is True
theItem.setType("FOLDER") item.setType("FOLDER")
assert theItem.describeMe() == "Folder" assert item.describeMe() == "Folder"
assert theItem.isFolderType() is True assert item.isFolderType() is True
theItem.setType("FILE") item.setType("FILE")
theItem.setLayout("DOCUMENT") item.setLayout("DOCUMENT")
assert theItem.isFileType() is True assert item.isFileType() is True
assert theItem.isDocumentLayout() is True assert item.isDocumentLayout() is True
theItem.setMainHeading("HH") item.setMainHeading("HH")
assert theItem.mainHeading == "H0" assert item.mainHeading == "H0"
assert theItem.describeMe() == "Novel Document" assert item.describeMe() == "Novel Document"
theItem.setMainHeading("H0") item.setMainHeading("H0")
assert theItem.mainHeading == "H0" assert item.mainHeading == "H0"
assert theItem.describeMe() == "Novel Document" assert item.describeMe() == "Novel Document"
theItem.setMainHeading("H1") item.setMainHeading("H1")
assert theItem.mainHeading == "H1" assert item.mainHeading == "H1"
assert theItem.describeMe() == "Novel Title Page" assert item.describeMe() == "Novel Title Page"
theItem.setMainHeading("H2") item.setMainHeading("H2")
assert theItem.mainHeading == "H2" assert item.mainHeading == "H2"
assert theItem.describeMe() == "Novel Chapter" assert item.describeMe() == "Novel Chapter"
theItem.setMainHeading("H3") item.setMainHeading("H3")
assert theItem.mainHeading == "H3" assert item.mainHeading == "H3"
assert theItem.describeMe() == "Novel Scene" assert item.describeMe() == "Novel Scene"
theItem.setMainHeading("H4") item.setMainHeading("H4")
assert theItem.mainHeading == "H4" assert item.mainHeading == "H4"
assert theItem.describeMe() == "Novel Section" assert item.describeMe() == "Novel Section"
theItem.setMainHeading("H5") item.setMainHeading("H5")
assert theItem.mainHeading == "H4" assert item.mainHeading == "H4"
assert theItem.describeMe() == "Novel Section" assert item.describeMe() == "Novel Section"
theItem.setLayout("NOTE") item.setLayout("NOTE")
assert theItem.isNoteLayout() is True assert item.isNoteLayout() is True
assert theItem.describeMe() == "Project Note" assert item.describeMe() == "Project Note"
# Status + Icon # Status + Icon
# ============= # =============
theItem.setType("FILE") item.setType("FILE")
theItem.setStatus(C.sNote) item.setStatus(C.sNote)
theItem.setImport(C.iMinor) item.setImport(C.iMinor)
theItem.setClass("NOVEL") item.setClass("NOVEL")
stT, stI = theItem.getImportStatus() stT, stI = item.getImportStatus()
assert stT == "Note" assert stT == "Note"
assert isinstance(stI, QIcon) assert isinstance(stI, QIcon)
theItem.setClass("CHARACTER") item.setClass("CHARACTER")
stT, stI = theItem.getImportStatus() stT, stI = item.getImportStatus()
assert stT == "Minor" assert stT == "Minor"
assert isinstance(stI, QIcon) assert isinstance(stI, QIcon)
# Representation # Representation
# ============== # ==============
theItem.setName("New Item") item.setName("New Item")
theItem.setParent("1111111111111") item.setParent("1111111111111")
assert repr(theItem) == "<NWItem handle=0000000000000, parent=1111111111111, name='New Item'>" assert repr(item) == "<NWItem handle=0000000000000, parent=1111111111111, name='New Item'>"
# Truthiness # Truthiness
# ========== # ==========
# Is True if the handle evaluates to True # Is True if the handle evaluates to True
assert bool(NWItem(theProject, "0000000000000")) is True assert bool(NWItem(project, "0000000000000")) is True
assert bool(NWItem(theProject, "")) is False assert bool(NWItem(project, "")) is False
# Copy an Item # Copy an Item
# ============ # ============
@@ -302,11 +302,11 @@ def testCoreItem_Methods(mockGUI, mockRnd, fncPath):
} }
# Get the scene item # Get the scene item
scItem = theProject.tree[C.hSceneDoc] scItem = project.tree[C.hSceneDoc]
assert isinstance(scItem, NWItem) assert isinstance(scItem, NWItem)
# Duplicate and update the expected content with a new handle # Duplicate and update the expected content with a new handle
cpHandle = theProject.tree._makeHandle() cpHandle = project.tree._makeHandle()
cpData = copy.deepcopy(scData) cpData = copy.deepcopy(scData)
cpData["itemAttr"]["handle"] = cpHandle cpData["itemAttr"]["handle"] = cpHandle
@@ -334,26 +334,26 @@ def testCoreItem_TypeSetter(mockGUI):
"""Test the setter for all the nwItemType values for the NWItem """Test the setter for all the nwItemType values for the NWItem
class. class.
""" """
theProject = NWProject() project = NWProject()
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
# Type # Type
theItem.setType(None) item.setType(None)
assert theItem.itemType == nwItemType.NO_TYPE assert item.itemType == nwItemType.NO_TYPE
theItem.setType("NONSENSE") item.setType("NONSENSE")
assert theItem.itemType == nwItemType.NO_TYPE assert item.itemType == nwItemType.NO_TYPE
theItem.setType("NO_TYPE") item.setType("NO_TYPE")
assert theItem.itemType == nwItemType.NO_TYPE assert item.itemType == nwItemType.NO_TYPE
theItem.setType("ROOT") item.setType("ROOT")
assert theItem.itemType == nwItemType.ROOT assert item.itemType == nwItemType.ROOT
theItem.setType("FOLDER") item.setType("FOLDER")
assert theItem.itemType == nwItemType.FOLDER assert item.itemType == nwItemType.FOLDER
theItem.setType("FILE") item.setType("FILE")
assert theItem.itemType == nwItemType.FILE assert item.itemType == nwItemType.FILE
# Alternative # Alternative
theItem.setType(nwItemType.ROOT) item.setType(nwItemType.ROOT)
assert theItem.itemType == nwItemType.ROOT assert item.itemType == nwItemType.ROOT
# END Test testCoreItem_TypeSetter # END Test testCoreItem_TypeSetter
@@ -363,84 +363,84 @@ def testCoreItem_ClassSetter(mockGUI):
"""Test the setter for all the nwItemClass values for the NWItem """Test the setter for all the nwItemClass values for the NWItem
class. class.
""" """
theProject = NWProject() project = NWProject()
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
# Class # Class
theItem.setClass(None) item.setClass(None)
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
theItem.setClass("NONSENSE") item.setClass("NONSENSE")
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
theItem.setClass("NO_CLASS") item.setClass("NO_CLASS")
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is True assert item.isInactiveClass() is True
theItem.setClass("NOVEL") item.setClass("NOVEL")
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
assert theItem.isNovelLike() is True assert item.isNovelLike() is True
assert theItem.documentAllowed() is True assert item.documentAllowed() is True
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("PLOT") item.setClass("PLOT")
assert theItem.itemClass == nwItemClass.PLOT assert item.itemClass == nwItemClass.PLOT
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("CHARACTER") item.setClass("CHARACTER")
assert theItem.itemClass == nwItemClass.CHARACTER assert item.itemClass == nwItemClass.CHARACTER
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("WORLD") item.setClass("WORLD")
assert theItem.itemClass == nwItemClass.WORLD assert item.itemClass == nwItemClass.WORLD
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("TIMELINE") item.setClass("TIMELINE")
assert theItem.itemClass == nwItemClass.TIMELINE assert item.itemClass == nwItemClass.TIMELINE
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("OBJECT") item.setClass("OBJECT")
assert theItem.itemClass == nwItemClass.OBJECT assert item.itemClass == nwItemClass.OBJECT
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("ENTITY") item.setClass("ENTITY")
assert theItem.itemClass == nwItemClass.ENTITY assert item.itemClass == nwItemClass.ENTITY
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("CUSTOM") item.setClass("CUSTOM")
assert theItem.itemClass == nwItemClass.CUSTOM assert item.itemClass == nwItemClass.CUSTOM
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is False assert item.documentAllowed() is False
assert theItem.isInactiveClass() is False assert item.isInactiveClass() is False
theItem.setClass("ARCHIVE") item.setClass("ARCHIVE")
assert theItem.itemClass == nwItemClass.ARCHIVE assert item.itemClass == nwItemClass.ARCHIVE
assert theItem.isNovelLike() is True assert item.isNovelLike() is True
assert theItem.documentAllowed() is True assert item.documentAllowed() is True
assert theItem.isInactiveClass() is True assert item.isInactiveClass() is True
theItem.setClass("TRASH") item.setClass("TRASH")
assert theItem.itemClass == nwItemClass.TRASH assert item.itemClass == nwItemClass.TRASH
assert theItem.isNovelLike() is False assert item.isNovelLike() is False
assert theItem.documentAllowed() is True assert item.documentAllowed() is True
assert theItem.isInactiveClass() is True assert item.isInactiveClass() is True
# Alternative # Alternative
theItem.setClass(nwItemClass.NOVEL) item.setClass(nwItemClass.NOVEL)
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
# END Test testCoreItem_ClassSetter # END Test testCoreItem_ClassSetter
@@ -450,26 +450,26 @@ def testCoreItem_LayoutSetter(mockGUI):
"""Test the setter for all the nwItemLayout values for the NWItem """Test the setter for all the nwItemLayout values for the NWItem
class. class.
""" """
theProject = NWProject() project = NWProject()
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
# Faulty Layouts # Faulty Layouts
theItem.setLayout(None) item.setLayout(None)
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setLayout("NONSENSE") item.setLayout("NONSENSE")
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
# Current Layouts # Current Layouts
theItem.setLayout("NO_LAYOUT") item.setLayout("NO_LAYOUT")
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setLayout("DOCUMENT") item.setLayout("DOCUMENT")
assert theItem.itemLayout == nwItemLayout.DOCUMENT assert item.itemLayout == nwItemLayout.DOCUMENT
theItem.setLayout("NOTE") item.setLayout("NOTE")
assert theItem.itemLayout == nwItemLayout.NOTE assert item.itemLayout == nwItemLayout.NOTE
# Alternative # Alternative
theItem.setLayout(nwItemLayout.NOTE) item.setLayout(nwItemLayout.NOTE)
assert theItem.itemLayout == nwItemLayout.NOTE assert item.itemLayout == nwItemLayout.NOTE
# END Test testCoreItem_LayoutSetter # END Test testCoreItem_LayoutSetter
@@ -478,54 +478,54 @@ def testCoreItem_LayoutSetter(mockGUI):
def testCoreItem_ClassDefaults(mockGUI): def testCoreItem_ClassDefaults(mockGUI):
"""Test the setter for the default values. """Test the setter for the default values.
""" """
theProject = NWProject() project = NWProject()
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
# Root items should not have their class updated # Root items should not have their class updated
theItem.setParent(None) item.setParent(None)
theItem.setClass(nwItemClass.NO_CLASS) item.setClass(nwItemClass.NO_CLASS)
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
theItem.setClassDefaults(nwItemClass.NOVEL) item.setClassDefaults(nwItemClass.NOVEL)
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
# Non-root items should have their class updated # Non-root items should have their class updated
theItem.setParent("0123456789abc") item.setParent("0123456789abc")
theItem.setClass(nwItemClass.NO_CLASS) item.setClass(nwItemClass.NO_CLASS)
assert theItem.itemClass == nwItemClass.NO_CLASS assert item.itemClass == nwItemClass.NO_CLASS
theItem.setClassDefaults(nwItemClass.NOVEL) item.setClassDefaults(nwItemClass.NOVEL)
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
# Non-layout items should have their layout set based on class # Non-layout items should have their layout set based on class
theItem.setParent("0123456789abc") item.setParent("0123456789abc")
theItem.setClass(nwItemClass.NO_CLASS) item.setClass(nwItemClass.NO_CLASS)
theItem.setLayout(nwItemLayout.NO_LAYOUT) item.setLayout(nwItemLayout.NO_LAYOUT)
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setClassDefaults(nwItemClass.NOVEL) item.setClassDefaults(nwItemClass.NOVEL)
assert theItem.itemLayout == nwItemLayout.DOCUMENT assert item.itemLayout == nwItemLayout.DOCUMENT
theItem.setParent("0123456789abc") item.setParent("0123456789abc")
theItem.setClass(nwItemClass.NO_CLASS) item.setClass(nwItemClass.NO_CLASS)
theItem.setLayout(nwItemLayout.NO_LAYOUT) item.setLayout(nwItemLayout.NO_LAYOUT)
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
theItem.setClassDefaults(nwItemClass.PLOT) item.setClassDefaults(nwItemClass.PLOT)
assert theItem.itemLayout == nwItemLayout.NOTE assert item.itemLayout == nwItemLayout.NOTE
# If documents are not allowed in that class, the layout should be changed # If documents are not allowed in that class, the layout should be changed
theItem.setParent("0123456789abc") item.setParent("0123456789abc")
theItem.setClass(nwItemClass.NO_CLASS) item.setClass(nwItemClass.NO_CLASS)
theItem.setLayout(nwItemLayout.DOCUMENT) item.setLayout(nwItemLayout.DOCUMENT)
assert theItem.itemLayout == nwItemLayout.DOCUMENT assert item.itemLayout == nwItemLayout.DOCUMENT
theItem.setClassDefaults(nwItemClass.PLOT) item.setClassDefaults(nwItemClass.PLOT)
assert theItem.itemLayout == nwItemLayout.NOTE assert item.itemLayout == nwItemLayout.NOTE
# In all cases, status and importance should no longer be None # In all cases, status and importance should no longer be None
assert theItem.itemStatus is not None assert item.itemStatus is not None
assert theItem.itemImport is not None assert item.itemImport is not None
# END Test testCoreItem_ClassDefaults # END Test testCoreItem_ClassDefaults
@@ -533,17 +533,17 @@ def testCoreItem_ClassDefaults(mockGUI):
@pytest.mark.core @pytest.mark.core
def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd): def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
"""Test packing and unpacking entries for the NWItem class.""" """Test packing and unpacking entries for the NWItem class."""
theProject = NWProject() project = NWProject()
theProject.data.itemStatus.write(None, "New", (100, 100, 100)) project.data.itemStatus.write(None, "New", (100, 100, 100))
theProject.data.itemImport.write(None, "New", (100, 100, 100)) project.data.itemImport.write(None, "New", (100, 100, 100))
# Invalid # Invalid
theItem = NWItem(theProject, "0000000000000") item = NWItem(project, "0000000000000")
assert theItem.unpack({}) is False assert item.unpack({}) is False
# File # File
theItem = NWItem(theProject, "") item = NWItem(project, "")
assert theItem.unpack({ assert item.unpack({
"name": "A File", "name": "A File",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
@@ -569,25 +569,25 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
}, },
}) is True }) is True
assert theItem.itemName == "A File" assert item.itemName == "A File"
assert theItem.itemHandle == "0000000000003" assert item.itemHandle == "0000000000003"
assert theItem.itemParent == "0000000000002" assert item.itemParent == "0000000000002"
assert theItem.itemRoot == "0000000000001" assert item.itemRoot == "0000000000001"
assert theItem.itemOrder == 1 assert item.itemOrder == 1
assert theItem.itemType == nwItemType.FILE assert item.itemType == nwItemType.FILE
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
assert theItem.itemLayout == nwItemLayout.DOCUMENT assert item.itemLayout == nwItemLayout.DOCUMENT
assert theItem.itemStatus == "s000000" assert item.itemStatus == "s000000"
assert theItem.itemImport == "i000001" assert item.itemImport == "i000001"
assert theItem.isActive is False assert item.isActive is False
assert theItem.isExpanded is True assert item.isExpanded is True
assert theItem.mainHeading == "H1" assert item.mainHeading == "H1"
assert theItem.charCount == 100 assert item.charCount == 100
assert theItem.wordCount == 20 assert item.wordCount == 20
assert theItem.paraCount == 2 assert item.paraCount == 2
assert theItem.cursorPos == 50 assert item.cursorPos == 50
assert theItem.pack() == { assert item.pack() == {
"name": "A File", "name": "A File",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
@@ -614,8 +614,8 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
} }
# Folder # Folder
theItem = NWItem(theProject, "") item = NWItem(project, "")
assert theItem.unpack({ assert item.unpack({
"name": "A Folder", "name": "A Folder",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
@@ -641,25 +641,25 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
} }
}) is True }) is True
assert theItem.itemName == "A Folder" assert item.itemName == "A Folder"
assert theItem.itemHandle == "0000000000003" assert item.itemHandle == "0000000000003"
assert theItem.itemParent == "0000000000002" assert item.itemParent == "0000000000002"
assert theItem.itemRoot == "0000000000001" assert item.itemRoot == "0000000000001"
assert theItem.itemOrder == 1 assert item.itemOrder == 1
assert theItem.itemType == nwItemType.FOLDER assert item.itemType == nwItemType.FOLDER
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
assert theItem.itemStatus == "s000000" assert item.itemStatus == "s000000"
assert theItem.itemImport == "i000001" assert item.itemImport == "i000001"
assert theItem.isActive is False assert item.isActive is False
assert theItem.isExpanded is True assert item.isExpanded is True
assert theItem.mainHeading == "H0" assert item.mainHeading == "H0"
assert theItem.charCount == 0 assert item.charCount == 0
assert theItem.wordCount == 0 assert item.wordCount == 0
assert theItem.paraCount == 0 assert item.paraCount == 0
assert theItem.cursorPos == 0 assert item.cursorPos == 0
assert theItem.pack() == { assert item.pack() == {
"name": "A Folder", "name": "A Folder",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
@@ -679,8 +679,8 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
} }
# Root # Root
theItem = NWItem(theProject, "") item = NWItem(project, "")
assert theItem.unpack({ assert item.unpack({
"name": "A Novel", "name": "A Novel",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
@@ -706,25 +706,25 @@ def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
}, },
}) is True }) is True
assert theItem.itemName == "A Novel" assert item.itemName == "A Novel"
assert theItem.itemHandle == "0000000000003" assert item.itemHandle == "0000000000003"
assert theItem.itemParent is None assert item.itemParent is None
assert theItem.itemRoot == "0000000000003" assert item.itemRoot == "0000000000003"
assert theItem.itemOrder == 1 assert item.itemOrder == 1
assert theItem.itemType == nwItemType.ROOT assert item.itemType == nwItemType.ROOT
assert theItem.itemClass == nwItemClass.NOVEL assert item.itemClass == nwItemClass.NOVEL
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT assert item.itemLayout == nwItemLayout.NO_LAYOUT
assert theItem.itemStatus == "s000000" assert item.itemStatus == "s000000"
assert theItem.itemImport == "i000001" assert item.itemImport == "i000001"
assert theItem.isActive is False assert item.isActive is False
assert theItem.isExpanded is True assert item.isExpanded is True
assert theItem.mainHeading == "H0" assert item.mainHeading == "H0"
assert theItem.charCount == 0 assert item.charCount == 0
assert theItem.wordCount == 0 assert item.wordCount == 0
assert theItem.paraCount == 0 assert item.paraCount == 0
assert theItem.cursorPos == 0 assert item.cursorPos == 0
assert theItem.pack() == { assert item.pack() == {
"name": "A Novel", "name": "A Novel",
"itemAttr": { "itemAttr": {
"handle": "0000000000003", "handle": "0000000000003",
+6 -6
View File
@@ -622,15 +622,15 @@ def testCoreProject_Backup(monkeypatch, mockGUI, fncPath, tstPaths):
# Test correct settings # Test correct settings
assert project.backupProject(doNotify=True) is True assert project.backupProject(doNotify=True) is True
theFiles = sorted((tstPaths.tmpDir / "Test Minimal").iterdir()) files = sorted((tstPaths.tmpDir / "Test Minimal").iterdir())
assert len(theFiles) in (1, 2) # Sometimes 2 due to clock tick assert len(files) in (1, 2) # Sometimes 2 due to clock tick
theZip = theFiles[0] zipFile = files[0]
assert theZip.name.startswith("Test Minimal") assert zipFile.name.startswith("Test Minimal")
assert theZip.suffix == ".zip" assert zipFile.suffix == ".zip"
# Extract the archive # Extract the archive
with ZipFile(tstPaths.tmpDir / "Test Minimal" / theZip.name, mode="r") as inZip: with ZipFile(tstPaths.tmpDir / "Test Minimal" / zipFile.name, mode="r") as inZip:
inZip.extractall(tstPaths.tmpDir / "extract") inZip.extractall(tstPaths.tmpDir / "extract")
# Check that the main project file was restored # Check that the main project file was restored
+136 -136
View File
@@ -36,8 +36,8 @@ importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
def testCoreStatus_Internal(mockRnd): def testCoreStatus_Internal(mockRnd):
"""Test all the internal functions of the NWStatus class. """Test all the internal functions of the NWStatus class.
""" """
theStatus = NWStatus(NWStatus.STATUS) nStatus = NWStatus(NWStatus.STATUS)
theImport = NWStatus(NWStatus.IMPORT) nImport = NWStatus(NWStatus.IMPORT)
with pytest.raises(Exception): with pytest.raises(Exception):
NWStatus(999) NWStatus(999)
@@ -45,42 +45,42 @@ def testCoreStatus_Internal(mockRnd):
# Generate Key # Generate Key
# ============ # ============
assert theStatus._newKey() == statusKeys[0] assert nStatus._newKey() == statusKeys[0]
assert theStatus._newKey() == statusKeys[1] assert nStatus._newKey() == statusKeys[1]
# Key collision, should move to key 3 # Key collision, should move to key 3
theStatus.write(statusKeys[2], "Crash", (0, 0, 0)) nStatus.write(statusKeys[2], "Crash", (0, 0, 0))
assert theStatus._newKey() == statusKeys[3] assert nStatus._newKey() == statusKeys[3]
assert theImport._newKey() == importKeys[0] assert nImport._newKey() == importKeys[0]
assert theImport._newKey() == importKeys[1] assert nImport._newKey() == importKeys[1]
# Key collision, should move to key 3 # Key collision, should move to key 3
theImport.write(importKeys[2], "Crash", (0, 0, 0)) nImport.write(importKeys[2], "Crash", (0, 0, 0))
assert theImport._newKey() == importKeys[3] assert nImport._newKey() == importKeys[3]
# Check Key # Check Key
# ========= # =========
assert theStatus._isKey(None) is False # Not a string assert nStatus._isKey(None) is False # Not a string
assert theStatus._isKey("s00000") is False # Too short assert nStatus._isKey("s00000") is False # Too short
assert theStatus._isKey("s000000") is True # Correct length assert nStatus._isKey("s000000") is True # Correct length
assert theStatus._isKey("s0000000") is False # Too long assert nStatus._isKey("s0000000") is False # Too long
assert theStatus._isKey("i000000") is False # Wrong type assert nStatus._isKey("i000000") is False # Wrong type
assert theStatus._isKey("q000000") is False # Wrong type assert nStatus._isKey("q000000") is False # Wrong type
assert theStatus._isKey("s12345H") is False # Not a hex value assert nStatus._isKey("s12345H") is False # Not a hex value
assert theStatus._isKey("s12345F") is False # Not a lower case hex value assert nStatus._isKey("s12345F") is False # Not a lower case hex value
assert theStatus._isKey("s12345f") is True # Valid hex value assert nStatus._isKey("s12345f") is True # Valid hex value
assert theImport._isKey(None) is False # Not a string assert nImport._isKey(None) is False # Not a string
assert theImport._isKey("i00000") is False # Too short assert nImport._isKey("i00000") is False # Too short
assert theImport._isKey("i000000") is True # Correct length assert nImport._isKey("i000000") is True # Correct length
assert theImport._isKey("i0000000") is False # Too long assert nImport._isKey("i0000000") is False # Too long
assert theImport._isKey("s000000") is False # Wrong type assert nImport._isKey("s000000") is False # Wrong type
assert theImport._isKey("q000000") is False # Wrong type assert nImport._isKey("q000000") is False # Wrong type
assert theImport._isKey("i12345H") is False # Not a hex value assert nImport._isKey("i12345H") is False # Not a hex value
assert theImport._isKey("i12345F") is False # Not a lower case hex value assert nImport._isKey("i12345F") is False # Not a lower case hex value
assert theImport._isKey("i12345f") is True # Valid hex value assert nImport._isKey("i12345f") is True # Valid hex value
# END Test testCoreStatus_Internal # END Test testCoreStatus_Internal
@@ -89,30 +89,30 @@ def testCoreStatus_Internal(mockRnd):
def testCoreStatus_Iterator(mockRnd): def testCoreStatus_Iterator(mockRnd):
"""Test the iterator functions of the NWStatus class. """Test the iterator functions of the NWStatus class.
""" """
theStatus = NWStatus(NWStatus.STATUS) nStatus = NWStatus(NWStatus.STATUS)
theStatus.write(None, "New", (100, 100, 100)) nStatus.write(None, "New", (100, 100, 100))
theStatus.write(None, "Note", (200, 50, 0)) nStatus.write(None, "Note", (200, 50, 0))
theStatus.write(None, "Draft", (200, 150, 0)) nStatus.write(None, "Draft", (200, 150, 0))
theStatus.write(None, "Finished", (50, 200, 0)) nStatus.write(None, "Finished", (50, 200, 0))
# Direct access # Direct access
entry = theStatus[statusKeys[0]] entry = nStatus[statusKeys[0]]
assert entry["cols"] == (100, 100, 100) assert entry["cols"] == (100, 100, 100)
assert entry["name"] == "New" assert entry["name"] == "New"
assert entry["count"] == 0 assert entry["count"] == 0
assert isinstance(entry["icon"], QIcon) assert isinstance(entry["icon"], QIcon)
# Iterate # Iterate
entries = list(theStatus) entries = list(nStatus)
assert len(entries) == 4 assert len(entries) == 4
assert len(theStatus) == 4 assert len(nStatus) == 4
# Keys # Keys
assert list(theStatus.keys()) == statusKeys assert list(nStatus.keys()) == statusKeys
# Items # Items
for index, (key, entry) in enumerate(theStatus.items()): for index, (key, entry) in enumerate(nStatus.items()):
assert key == statusKeys[index] assert key == statusKeys[index]
assert "cols" in entry assert "cols" in entry
assert "name" in entry assert "name" in entry
@@ -120,7 +120,7 @@ def testCoreStatus_Iterator(mockRnd):
assert "icon" in entry assert "icon" in entry
# Valuse # Valuse
for entry in theStatus.values(): for entry in nStatus.values():
assert "cols" in entry assert "cols" in entry
assert "name" in entry assert "name" in entry
assert "count" in entry assert "count" in entry
@@ -133,67 +133,67 @@ def testCoreStatus_Iterator(mockRnd):
def testCoreStatus_Entries(mockRnd): def testCoreStatus_Entries(mockRnd):
"""Test all the simple setters for the NWStatus class. """Test all the simple setters for the NWStatus class.
""" """
theStatus = NWStatus(NWStatus.STATUS) nStatus = NWStatus(NWStatus.STATUS)
# Write # Write
# ===== # =====
# Have a key # Have a key
theStatus.write(statusKeys[0], "Entry 1", (200, 100, 50)) nStatus.write(statusKeys[0], "Entry 1", (200, 100, 50))
assert theStatus[statusKeys[0]]["name"] == "Entry 1" assert nStatus[statusKeys[0]]["name"] == "Entry 1"
assert theStatus[statusKeys[0]]["cols"] == (200, 100, 50) assert nStatus[statusKeys[0]]["cols"] == (200, 100, 50)
# Don't have a key # Don't have a key
theStatus.write(None, "Entry 2", (210, 110, 60)) nStatus.write(None, "Entry 2", (210, 110, 60))
assert theStatus[statusKeys[1]]["name"] == "Entry 2" assert nStatus[statusKeys[1]]["name"] == "Entry 2"
assert theStatus[statusKeys[1]]["cols"] == (210, 110, 60) assert nStatus[statusKeys[1]]["cols"] == (210, 110, 60)
# Wrong colour spec # Wrong colour spec
theStatus.write(None, "Entry 3", "what?") nStatus.write(None, "Entry 3", "what?")
assert theStatus[statusKeys[2]]["name"] == "Entry 3" assert nStatus[statusKeys[2]]["name"] == "Entry 3"
assert theStatus[statusKeys[2]]["cols"] == (100, 100, 100) assert nStatus[statusKeys[2]]["cols"] == (100, 100, 100)
# Wrong colour count # Wrong colour count
theStatus.write(None, "Entry 4", (10, 20)) nStatus.write(None, "Entry 4", (10, 20))
assert theStatus[statusKeys[3]]["name"] == "Entry 4" assert nStatus[statusKeys[3]]["name"] == "Entry 4"
assert theStatus[statusKeys[3]]["cols"] == (100, 100, 100) assert nStatus[statusKeys[3]]["cols"] == (100, 100, 100)
# Check # Check
# ===== # =====
# Normal lookup # Normal lookup
for key in statusKeys: for key in statusKeys:
assert theStatus.check(key) == key assert nStatus.check(key) == key
# Non-existing name # Non-existing name
assert theStatus.check("s987654") == statusKeys[0] assert nStatus.check("s987654") == statusKeys[0]
# Name Access # Name Access
# =========== # ===========
assert theStatus.name(statusKeys[0]) == "Entry 1" assert nStatus.name(statusKeys[0]) == "Entry 1"
assert theStatus.name(statusKeys[1]) == "Entry 2" assert nStatus.name(statusKeys[1]) == "Entry 2"
assert theStatus.name(statusKeys[2]) == "Entry 3" assert nStatus.name(statusKeys[2]) == "Entry 3"
assert theStatus.name(statusKeys[3]) == "Entry 4" assert nStatus.name(statusKeys[3]) == "Entry 4"
assert theStatus.name("blablabla") == "Entry 1" assert nStatus.name("blablabla") == "Entry 1"
# Colour Access # Colour Access
# ============= # =============
assert theStatus.cols(statusKeys[0]) == (200, 100, 50) assert nStatus.cols(statusKeys[0]) == (200, 100, 50)
assert theStatus.cols(statusKeys[1]) == (210, 110, 60) assert nStatus.cols(statusKeys[1]) == (210, 110, 60)
assert theStatus.cols(statusKeys[2]) == (100, 100, 100) assert nStatus.cols(statusKeys[2]) == (100, 100, 100)
assert theStatus.cols(statusKeys[3]) == (100, 100, 100) assert nStatus.cols(statusKeys[3]) == (100, 100, 100)
assert theStatus.cols("blablabla") == (200, 100, 50) assert nStatus.cols("blablabla") == (200, 100, 50)
# Icon Access # Icon Access
# =========== # ===========
assert isinstance(theStatus.icon(statusKeys[0]), QIcon) assert isinstance(nStatus.icon(statusKeys[0]), QIcon)
assert isinstance(theStatus.icon(statusKeys[1]), QIcon) assert isinstance(nStatus.icon(statusKeys[1]), QIcon)
assert isinstance(theStatus.icon(statusKeys[2]), QIcon) assert isinstance(nStatus.icon(statusKeys[2]), QIcon)
assert isinstance(theStatus.icon(statusKeys[3]), QIcon) assert isinstance(nStatus.icon(statusKeys[3]), QIcon)
assert isinstance(theStatus.icon("blablabla"), QIcon) assert isinstance(nStatus.icon("blablabla"), QIcon)
# Increment and Count Access # Increment and Count Access
# ========================== # ==========================
@@ -201,32 +201,32 @@ def testCoreStatus_Entries(mockRnd):
countTo = [3, 5, 7, 9] countTo = [3, 5, 7, 9]
for i, n in enumerate(countTo): for i, n in enumerate(countTo):
for _ in range(n): for _ in range(n):
theStatus.increment(statusKeys[i]) nStatus.increment(statusKeys[i])
assert theStatus.count(statusKeys[0]) == countTo[0] assert nStatus.count(statusKeys[0]) == countTo[0]
assert theStatus.count(statusKeys[1]) == countTo[1] assert nStatus.count(statusKeys[1]) == countTo[1]
assert theStatus.count(statusKeys[2]) == countTo[2] assert nStatus.count(statusKeys[2]) == countTo[2]
assert theStatus.count(statusKeys[3]) == countTo[3] assert nStatus.count(statusKeys[3]) == countTo[3]
assert theStatus.count("blablabla") == countTo[0] assert nStatus.count("blablabla") == countTo[0]
theStatus.resetCounts() nStatus.resetCounts()
assert theStatus.count(statusKeys[0]) == 0 assert nStatus.count(statusKeys[0]) == 0
assert theStatus.count(statusKeys[1]) == 0 assert nStatus.count(statusKeys[1]) == 0
assert theStatus.count(statusKeys[2]) == 0 assert nStatus.count(statusKeys[2]) == 0
assert theStatus.count(statusKeys[3]) == 0 assert nStatus.count(statusKeys[3]) == 0
# Reorder # Reorder
# ======= # =======
cOrder = list(theStatus.keys()) cOrder = list(nStatus.keys())
assert cOrder == statusKeys assert cOrder == statusKeys
# Wrong length # Wrong length
assert theStatus.reorder([]) is False assert nStatus.reorder([]) is False
# No change # No change
assert theStatus.reorder(cOrder) is False assert nStatus.reorder(cOrder) is False
# Actual reaorder # Actual reaorder
nOrder = [ nOrder = [
@@ -235,63 +235,63 @@ def testCoreStatus_Entries(mockRnd):
statusKeys[1], statusKeys[1],
statusKeys[3], statusKeys[3],
] ]
assert theStatus.reorder(nOrder) is True assert nStatus.reorder(nOrder) is True
assert list(theStatus.keys()) == nOrder assert list(nStatus.keys()) == nOrder
# Add an unknown key # Add an unknown key
wOrder = nOrder.copy() wOrder = nOrder.copy()
wOrder[3] = theStatus._newKey() wOrder[3] = nStatus._newKey()
assert theStatus.reorder(wOrder) is False assert nStatus.reorder(wOrder) is False
assert list(theStatus.keys()) == nOrder assert list(nStatus.keys()) == nOrder
# Put it back # Put it back
assert theStatus.reorder(cOrder) is True assert nStatus.reorder(cOrder) is True
assert list(theStatus.keys()) == cOrder assert list(nStatus.keys()) == cOrder
# Default # Default
# ======= # =======
default = theStatus._default default = nStatus._default
theStatus._default = None nStatus._default = None
assert theStatus.check("Entry 5") == "" assert nStatus.check("Entry 5") == ""
assert theStatus.name("blablabla") == "" assert nStatus.name("blablabla") == ""
assert theStatus.cols("blablabla") == (100, 100, 100) assert nStatus.cols("blablabla") == (100, 100, 100)
assert theStatus.count("blablabla") == 0 assert nStatus.count("blablabla") == 0
assert isinstance(theStatus.icon("blablabla"), QIcon) assert isinstance(nStatus.icon("blablabla"), QIcon)
theStatus._default = default nStatus._default = default
# Remove # Remove
# ====== # ======
# Non-existing entry # Non-existing entry
assert theStatus.remove("blablabla") is False assert nStatus.remove("blablabla") is False
# Non-zero entry # Non-zero entry
theStatus.increment(statusKeys[3]) nStatus.increment(statusKeys[3])
assert theStatus.remove(statusKeys[3]) is False assert nStatus.remove(statusKeys[3]) is False
# Delete last entry # Delete last entry
theStatus.resetCounts() nStatus.resetCounts()
lastName = theStatus.name(statusKeys[3]) lastName = nStatus.name(statusKeys[3])
assert lastName == "Entry 4" assert lastName == "Entry 4"
assert theStatus.remove(statusKeys[3]) is True assert nStatus.remove(statusKeys[3]) is True
assert theStatus.check(statusKeys[3]) == theStatus._default assert nStatus.check(statusKeys[3]) == nStatus._default
assert theStatus.check(lastName) == theStatus._default assert nStatus.check(lastName) == nStatus._default
# Delete default entry, Entry 2 is new default # Delete default entry, Entry 2 is new default
firstName = theStatus.name(theStatus._default) firstName = nStatus.name(nStatus._default)
assert firstName == "Entry 1" assert firstName == "Entry 1"
assert theStatus.remove(theStatus._default) is True assert nStatus.remove(nStatus._default) is True
assert theStatus.name(firstName) == "Entry 2" assert nStatus.name(firstName) == "Entry 2"
# Remove remaining entries # Remove remaining entries
assert theStatus.remove(statusKeys[1]) is True assert nStatus.remove(statusKeys[1]) is True
assert theStatus.remove(statusKeys[2]) is True assert nStatus.remove(statusKeys[2]) is True
assert len(theStatus) == 0 assert len(nStatus) == 0
assert theStatus._default is None assert nStatus._default is None
# END Test testCoreStatus_Entries # END Test testCoreStatus_Entries
@@ -300,19 +300,19 @@ def testCoreStatus_Entries(mockRnd):
def testCoreStatus_PackUnpack(mockRnd): def testCoreStatus_PackUnpack(mockRnd):
"""Test all the pack/unpack of the NWStatus class. """Test all the pack/unpack of the NWStatus class.
""" """
theStatus = NWStatus(NWStatus.STATUS) nStatus = NWStatus(NWStatus.STATUS)
theStatus.write(None, "New", (100, 100, 100)) nStatus.write(None, "New", (100, 100, 100))
theStatus.write(None, "Note", (200, 50, 0)) nStatus.write(None, "Note", (200, 50, 0))
theStatus.write(None, "Draft", (200, 150, 0)) nStatus.write(None, "Draft", (200, 150, 0))
theStatus.write(None, "Finished", (50, 200, 0)) nStatus.write(None, "Finished", (50, 200, 0))
countTo = [3, 5, 7, 9] countTo = [3, 5, 7, 9]
for i, n in enumerate(countTo): for i, n in enumerate(countTo):
for _ in range(n): for _ in range(n):
theStatus.increment(statusKeys[i]) nStatus.increment(statusKeys[i])
# Pack # Pack
assert list(theStatus.pack()) == [ assert list(nStatus.pack()) == [
("New", { ("New", {
"key": statusKeys[0], "key": statusKeys[0],
"count": "3", "count": "3",
@@ -344,26 +344,26 @@ def testCoreStatus_PackUnpack(mockRnd):
] ]
# Unpack # Unpack
theStatus = NWStatus(NWStatus.STATUS) nStatus = NWStatus(NWStatus.STATUS)
theStatus.unpack({ nStatus.unpack({
statusKeys[0]: {"label": "New0", "colour": (100, 100, 100), "count": countTo[0]}, statusKeys[0]: {"label": "New0", "colour": (100, 100, 100), "count": countTo[0]},
statusKeys[1]: {"label": "New1", "colour": (150, 150, 150), "count": countTo[1]}, statusKeys[1]: {"label": "New1", "colour": (150, 150, 150), "count": countTo[1]},
statusKeys[2]: {"label": "New2", "colour": (200, 200, 200), "count": countTo[2]}, statusKeys[2]: {"label": "New2", "colour": (200, 200, 200), "count": countTo[2]},
statusKeys[3]: {"label": "New3", "colour": (250, 250, 250), "count": countTo[3]}, statusKeys[3]: {"label": "New3", "colour": (250, 250, 250), "count": countTo[3]},
}) })
assert len(theStatus._store) == 4 assert len(nStatus._store) == 4
assert list(theStatus._store.keys()) == statusKeys assert list(nStatus._store.keys()) == statusKeys
assert theStatus._store[statusKeys[0]]["name"] == "New0" assert nStatus._store[statusKeys[0]]["name"] == "New0"
assert theStatus._store[statusKeys[1]]["name"] == "New1" assert nStatus._store[statusKeys[1]]["name"] == "New1"
assert theStatus._store[statusKeys[2]]["name"] == "New2" assert nStatus._store[statusKeys[2]]["name"] == "New2"
assert theStatus._store[statusKeys[3]]["name"] == "New3" assert nStatus._store[statusKeys[3]]["name"] == "New3"
assert theStatus._store[statusKeys[0]]["cols"] == (100, 100, 100) assert nStatus._store[statusKeys[0]]["cols"] == (100, 100, 100)
assert theStatus._store[statusKeys[1]]["cols"] == (150, 150, 150) assert nStatus._store[statusKeys[1]]["cols"] == (150, 150, 150)
assert theStatus._store[statusKeys[2]]["cols"] == (200, 200, 200) assert nStatus._store[statusKeys[2]]["cols"] == (200, 200, 200)
assert theStatus._store[statusKeys[3]]["cols"] == (250, 250, 250) assert nStatus._store[statusKeys[3]]["cols"] == (250, 250, 250)
assert theStatus._store[statusKeys[0]]["count"] == countTo[0] assert nStatus._store[statusKeys[0]]["count"] == countTo[0]
assert theStatus._store[statusKeys[1]]["count"] == countTo[1] assert nStatus._store[statusKeys[1]]["count"] == countTo[1]
assert theStatus._store[statusKeys[2]]["count"] == countTo[2] assert nStatus._store[statusKeys[2]]["count"] == countTo[2]
assert theStatus._store[statusKeys[3]]["count"] == countTo[3] assert nStatus._store[statusKeys[3]]["count"] == countTo[3]
# END Test testCoreStatus_PackUnpack # END Test testCoreStatus_PackUnpack
+4 -4
View File
@@ -266,13 +266,13 @@ 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() project = NWProject()
storage = theProject.storage storage = project.storage
assert storage.zipIt(zipFile) is False assert storage.zipIt(zipFile) is False
# Make a project # Make a project
mockRnd.reset() mockRnd.reset()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
# Fail to create archive # Fail to create archive
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
@@ -292,7 +292,7 @@ def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
assert f"content/{C.hChapterDoc}.nwd" in names assert f"content/{C.hChapterDoc}.nwd" in names
assert f"content/{C.hSceneDoc}.nwd" in names assert f"content/{C.hSceneDoc}.nwd" in names
theProject.closeProject() project.closeProject()
# END Test testCoreStorage_ZipIt # END Test testCoreStorage_ZipIt
+48 -48
View File
@@ -45,7 +45,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "# Partition\n" html._text = "# Partition\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: center;'>Partition</h1>\n" "<h1 class='title' style='text-align: center;'>Partition</h1>\n"
) )
@@ -53,7 +53,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "## Chapter Title\n" html._text = "## Chapter Title\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 style='page-break-before: always;'>Chapter Title</h1>\n" "<h1 style='page-break-before: always;'>Chapter Title</h1>\n"
) )
@@ -61,19 +61,19 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "### Scene Title\n" html._text = "### Scene Title\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h2>Scene Title</h2>\n" assert html.result == "<h2>Scene Title</h2>\n"
# Header 4 # Header 4
html._text = "#### Section Title\n" html._text = "#### Section Title\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h3>Section Title</h3>\n" assert html.result == "<h3>Section Title</h3>\n"
# Title # Title
html._text = "#! Title\n" html._text = "#! Title\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: center;'>Title</h1>\n" "<h1 class='title' style='text-align: center;'>Title</h1>\n"
) )
@@ -81,7 +81,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "##! Prologue\n" html._text = "##! Prologue\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h1 style='page-break-before: always;'>Prologue</h1>\n" assert html.result == "<h1 style='page-break-before: always;'>Prologue</h1>\n"
# Note Files Headers # Note Files Headers
# ================== # ==================
@@ -95,31 +95,31 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "# Heading One\n" html._text = "# Heading One\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h1><a name='T0001'></a>Heading One</h1>\n" assert html.result == "<h1><a name='T0001'></a>Heading One</h1>\n"
# Header 2 # Header 2
html._text = "## Heading Two\n" html._text = "## Heading Two\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h2><a name='T0001'></a>Heading Two</h2>\n" assert html.result == "<h2><a name='T0001'></a>Heading Two</h2>\n"
# Header 3 # Header 3
html._text = "### Heading Three\n" html._text = "### Heading Three\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h3><a name='T0001'></a>Heading Three</h3>\n" assert html.result == "<h3><a name='T0001'></a>Heading Three</h3>\n"
# Header 4 # Header 4
html._text = "#### Heading Four\n" html._text = "#### Heading Four\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h4><a name='T0001'></a>Heading Four</h4>\n" assert html.result == "<h4><a name='T0001'></a>Heading Four</h4>\n"
# Title # Title
html._text = "#! Heading One\n" html._text = "#! Heading One\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 style='text-align: center;'><a name='T0001'></a>Heading One</h1>\n" "<h1 style='text-align: center;'><a name='T0001'></a>Heading One</h1>\n"
) )
@@ -127,7 +127,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "##! Heading Two\n" html._text = "##! Heading Two\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "<h2><a name='T0001'></a>Heading Two</h2>\n" assert html.result == "<h2><a name='T0001'></a>Heading Two</h2>\n"
# Paragraphs # Paragraphs
# ========== # ==========
@@ -136,7 +136,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Some <strong>nested bold and <em>italic</em> and " "<p>Some <strong>nested bold and <em>italic</em> and "
"<del>strikethrough</del> text</strong> here</p>\n" "<del>strikethrough</del> text</strong> here</p>\n"
) )
@@ -145,7 +145,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "Line one \nLine two \nLine three\n" html._text = "Line one \nLine two \nLine three\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p class='break'>Line one<br/>Line two<br/>Line three</p>\n" "<p class='break'>Line one<br/>Line two<br/>Line three</p>\n"
) )
@@ -153,13 +153,13 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "%synopsis: The synopsis ...\n" html._text = "%synopsis: The synopsis ...\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "" assert html.result == ""
html.setSynopsis(True) html.setSynopsis(True)
html._text = "%synopsis: The synopsis ...\n" html._text = "%synopsis: The synopsis ...\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n" "<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n"
) )
@@ -167,7 +167,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "%short: A short description ...\n" html._text = "%short: A short description ...\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p class='synopsis'><strong>Short Description:</strong> A short description ...</p>\n" "<p class='synopsis'><strong>Short Description:</strong> A short description ...</p>\n"
) )
@@ -175,13 +175,13 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "% A comment ...\n" html._text = "% A comment ...\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "" assert html.result == ""
html.setComments(True) html.setComments(True)
html._text = "% A comment ...\n" html._text = "% A comment ...\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p class='comment'><strong>Comment:</strong> A comment ...</p>\n" "<p class='comment'><strong>Comment:</strong> A comment ...</p>\n"
) )
@@ -189,13 +189,13 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "@char: Bod, Jane\n" html._text = "@char: Bod, Jane\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == "" assert html.result == ""
html.setKeywords(True) html.setKeywords(True)
html._text = "@char: Bod, Jane\n" html._text = "@char: Bod, Jane\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p><span class='tags'>Characters:</span> " "<p><span class='tags'>Characters:</span> "
"<a href='#tag_Bod'>Bod</a>, <a href='#tag_Jane'>Jane</a></p>\n" "<a href='#tag_Bod'>Bod</a>, <a href='#tag_Jane'>Jane</a></p>\n"
) )
@@ -205,7 +205,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n" html._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h2>" "<h2>"
"<a name='T0001'></a>Chapter</h2>\n" "<a name='T0001'></a>Chapter</h2>\n"
"<p style='margin-bottom: 0;'>" "<p style='margin-bottom: 0;'>"
@@ -228,7 +228,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Some <b>nested bold and <i>italic</i> and " "<p>Some <b>nested bold and <i>italic</i> and "
"<span style='text-decoration: line-through;'>strikethrough</span> " "<span style='text-decoration: line-through;'>strikethrough</span> "
"text</b> here</p>\n" "text</b> here</p>\n"
@@ -256,7 +256,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 1, "", None, html.A_NONE), (html.T_EMPTY, 1, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>" "<h1 class='title' style='text-align: center; page-break-before: always;'>"
"<a name='T0001'></a>A Title</h1>\n" "<a name='T0001'></a>A Title</h1>\n"
) )
@@ -267,7 +267,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 1, "", None, html.A_NONE), (html.T_EMPTY, 1, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 style='page-break-before: always;'>" "<h1 style='page-break-before: always;'>"
"<a name='T0001'></a>Prologue</h1>\n" "<a name='T0001'></a>Prologue</h1>\n"
) )
@@ -281,7 +281,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 1, "", None, html.A_NONE), (html.T_EMPTY, 1, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == "<p class='sep' style='text-align: center;'>* * *</p>\n" assert html.result == "<p class='sep' style='text-align: center;'>* * *</p>\n"
# Skip # Skip
html._tokens = [ html._tokens = [
@@ -289,7 +289,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 1, "", None, html.A_NONE), (html.T_EMPTY, 1, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == "<p class='skip'>&nbsp;</p>\n" assert html.result == "<p class='skip'>&nbsp;</p>\n"
# Alignment # Alignment
# ========= # =========
@@ -302,7 +302,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_LEFT), (html.T_HEAD1, 1, "A Title", None, html.A_LEFT),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title'>A Title</h1>\n" "<h1 class='title'>A Title</h1>\n"
) )
@@ -313,7 +313,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_LEFT), (html.T_HEAD1, 1, "A Title", None, html.A_LEFT),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: left;'>A Title</h1>\n" "<h1 class='title' style='text-align: left;'>A Title</h1>\n"
) )
@@ -322,7 +322,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_RIGHT), (html.T_HEAD1, 1, "A Title", None, html.A_RIGHT),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: right;'>A Title</h1>\n" "<h1 class='title' style='text-align: right;'>A Title</h1>\n"
) )
@@ -331,7 +331,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_CENTRE), (html.T_HEAD1, 1, "A Title", None, html.A_CENTRE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: center;'>A Title</h1>\n" "<h1 class='title' style='text-align: center;'>A Title</h1>\n"
) )
@@ -340,7 +340,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_JUSTIFY), (html.T_HEAD1, 1, "A Title", None, html.A_JUSTIFY),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' style='text-align: justify;'>A Title</h1>\n" "<h1 class='title' style='text-align: justify;'>A Title</h1>\n"
) )
@@ -352,7 +352,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_HEAD1, 1, "A Title", None, html.A_PBB | html.A_PBA), (html.T_HEAD1, 1, "A Title", None, html.A_PBB | html.A_PBA),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 class='title' " "<h1 class='title' "
"style='page-break-before: always; page-break-after: always;'>A Title</h1>\n" "style='page-break-before: always; page-break-after: always;'>A Title</h1>\n"
) )
@@ -366,7 +366,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 2, "", None, html.A_NONE), (html.T_EMPTY, 2, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p style='margin-left: 40px;'>Some text ...</p>\n" "<p style='margin-left: 40px;'>Some text ...</p>\n"
) )
@@ -376,7 +376,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(html.T_EMPTY, 2, "", None, html.A_NONE), (html.T_EMPTY, 2, "", None, html.A_NONE),
] ]
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p style='margin-right: 40px;'>Some text ...</p>\n" "<p style='margin-right: 40px;'>Some text ...</p>\n"
) )
@@ -396,28 +396,28 @@ def testCoreToHtml_SpecialCases(mockGUI):
html._text = "Text with > and < with some **bold text** in it.\n" html._text = "Text with > and < with some **bold text** in it.\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Text with &gt; and &lt; with some <strong>bold text</strong> in it.</p>\n" "<p>Text with &gt; and &lt; with some <strong>bold text</strong> in it.</p>\n"
) )
html._text = "Text with some <**bold text**> in it.\n" html._text = "Text with some <**bold text**> in it.\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Text with some &lt;<strong>bold text</strong>&gt; in it.</p>\n" "<p>Text with some &lt;<strong>bold text</strong>&gt; in it.</p>\n"
) )
html._text = "Let's > be > _difficult **shall** > we_?\n" html._text = "Let's > be > _difficult **shall** > we_?\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Let's &gt; be &gt; <em>difficult <strong>shall</strong> &gt; we</em>?</p>\n" "<p>Let's &gt; be &gt; <em>difficult <strong>shall</strong> &gt; we</em>?</p>\n"
) )
html._text = "Test > text _<**bold**>_ and more.\n" html._text = "Test > text _<**bold**>_ and more.\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Test &gt; text <em>&lt;<strong>bold</strong>&gt;</em> and more.</p>\n" "<p>Test &gt; text <em>&lt;<strong>bold</strong>&gt;</em> and more.</p>\n"
) )
@@ -429,7 +429,7 @@ def testCoreToHtml_SpecialCases(mockGUI):
html._text = "% Test > text _<**bold**>_ and more.\n" html._text = "% Test > text _<**bold**>_ and more.\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p class='comment'>" "<p class='comment'>"
"<strong>Comment:</strong> Test &gt; text _&lt;**bold**&gt;_ and more." "<strong>Comment:</strong> Test &gt; text _&lt;**bold**&gt;_ and more."
"</p>\n" "</p>\n"
@@ -438,7 +438,7 @@ def testCoreToHtml_SpecialCases(mockGUI):
html._text = "## Heading <1>\n" html._text = "## Heading <1>\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<h1 style='page-break-before: always;'>Heading &lt;1&gt;</h1>\n" "<h1 style='page-break-before: always;'>Heading &lt;1&gt;</h1>\n"
) )
@@ -449,7 +449,7 @@ def testCoreToHtml_SpecialCases(mockGUI):
html._text = "Test text \\**_bold_** and more.\n" html._text = "Test text \\**_bold_** and more.\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Test text **<em>bold</em>** and more.</p>\n" "<p>Test text **<em>bold</em>** and more.</p>\n"
) )
@@ -511,7 +511,7 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
html.doPreProcessing() html.doPreProcessing()
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == resText[i] assert html.result == resText[i]
assert html.fullHTML == resText assert html.fullHTML == resText
@@ -521,7 +521,7 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
# Check File # Check File
# ========== # ==========
theStyle = html.getStyleSheet() hStyle = html.getStyleSheet()
htmlDoc = ( htmlDoc = (
"<!DOCTYPE html>\n" "<!DOCTYPE html>\n"
"<html>\n" "<html>\n"
@@ -539,7 +539,7 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
"</body>\n" "</body>\n"
"</html>\n" "</html>\n"
).format( ).format(
htmlStyle="\n".join(theStyle), htmlStyle="\n".join(hStyle),
bodyText="".join(resText).rstrip() bodyText="".join(resText).rstrip()
) )
@@ -564,7 +564,7 @@ def testCoreToHtml_Methods(mockGUI):
html.doPreProcessing() html.doPreProcessing()
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Text with &lt;brackets&gt; &amp; shortdash, long—dash …</p>\n" "<p>Text with &lt;brackets&gt; &amp; shortdash, long—dash …</p>\n"
) )
@@ -575,7 +575,7 @@ def testCoreToHtml_Methods(mockGUI):
html.doPreProcessing() html.doPreProcessing()
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theResult == ( assert html.result == (
"<p>Text with &lt;brackets&gt; &amp; short&ndash;dash, long&mdash;dash &hellip;</p>\n" "<p>Text with &lt;brackets&gt; &amp; short&ndash;dash, long&mdash;dash &hellip;</p>\n"
) )
@@ -585,7 +585,7 @@ def testCoreToHtml_Methods(mockGUI):
html.doPreProcessing() html.doPreProcessing()
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html.theMarkdown[-1] == ( assert html.allMarkdown[-1] == (
"Text with <brackets> &amp; short&ndash;dash, long&mdash;dash &hellip;\n\n" "Text with <brackets> &amp; short&ndash;dash, long&mdash;dash &hellip;\n\n"
) )
+33 -33
View File
@@ -168,14 +168,14 @@ def testCoreToken_TextOps(monkeypatch, mockGUI, mockRnd, fncPath):
# First Page # First Page
assert tokens.addRootHeading(C.hPlotRoot) is True assert tokens.addRootHeading(C.hPlotRoot) is True
assert tokens.theMarkdown[-1] == "# Notes: Plot\n\n" assert tokens.allMarkdown[-1] == "# Notes: Plot\n\n"
assert tokens._tokens[-1] == ( assert tokens._tokens[-1] == (
Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE
) )
# Not First Page # Not First Page
assert tokens.addRootHeading(C.hPlotRoot) is True assert tokens.addRootHeading(C.hPlotRoot) is True
assert tokens.theMarkdown[-1] == "# Notes: Plot\n\n" assert tokens.allMarkdown[-1] == "# Notes: Plot\n\n"
assert tokens._tokens[-1] == ( assert tokens._tokens[-1] == (
Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB Tokenizer.T_TITLE, 0, "Notes: Plot", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB
) )
@@ -250,7 +250,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_CENTRE), (Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#! Novel Title\n\n" assert tokens.allMarkdown[-1] == "#! Novel Title\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -263,7 +263,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_CENTRE), (Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#! Note Title\n\n" assert tokens.allMarkdown[-1] == "#! Note Title\n\n"
# Header 1 # Header 1
# ======== # ========
@@ -279,7 +279,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD1, 1, "Novel Title", None, Tokenizer.A_CENTRE), (Tokenizer.T_HEAD1, 1, "Novel Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "# Novel Title\n\n" assert tokens.allMarkdown[-1] == "# Novel Title\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -292,7 +292,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD1, 1, "Note Title", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "# Note Title\n\n" assert tokens.allMarkdown[-1] == "# Note Title\n\n"
# Header 2 # Header 2
# ======== # ========
@@ -307,7 +307,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD2, 1, "Chapter One", None, Tokenizer.A_PBB), (Tokenizer.T_HEAD2, 1, "Chapter One", None, Tokenizer.A_PBB),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "## Chapter One\n\n" assert tokens.allMarkdown[-1] == "## Chapter One\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -319,7 +319,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD2, 1, "Heading 2", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD2, 1, "Heading 2", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "## Heading 2\n\n" assert tokens.allMarkdown[-1] == "## Heading 2\n\n"
# Header 3 # Header 3
# ======== # ========
@@ -334,7 +334,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD3, 1, "Scene One", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD3, 1, "Scene One", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "### Scene One\n\n" assert tokens.allMarkdown[-1] == "### Scene One\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -346,7 +346,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD3, 1, "Heading 3", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD3, 1, "Heading 3", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "### Heading 3\n\n" assert tokens.allMarkdown[-1] == "### Heading 3\n\n"
# Header 4 # Header 4
# ======== # ========
@@ -361,7 +361,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD4, 1, "A Section", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD4, 1, "A Section", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#### A Section\n\n" assert tokens.allMarkdown[-1] == "#### A Section\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -373,7 +373,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD4, 1, "Heading 4", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD4, 1, "Heading 4", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#### Heading 4\n\n" assert tokens.allMarkdown[-1] == "#### Heading 4\n\n"
# Title # Title
# ===== # =====
@@ -388,7 +388,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_TITLE, 1, "Title", None, Tokenizer.A_CENTRE), (Tokenizer.T_TITLE, 1, "Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#! Title\n\n" assert tokens.allMarkdown[-1] == "#! Title\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -400,7 +400,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD1, 1, "Title", None, Tokenizer.A_CENTRE), (Tokenizer.T_HEAD1, 1, "Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "#! Title\n\n" assert tokens.allMarkdown[-1] == "#! Title\n\n"
# Unnumbered # Unnumbered
# ========== # ==========
@@ -415,7 +415,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_UNNUM, 1, "Prologue", None, Tokenizer.A_PBB), (Tokenizer.T_UNNUM, 1, "Prologue", None, Tokenizer.A_PBB),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "##! Prologue\n\n" assert tokens.allMarkdown[-1] == "##! Prologue\n\n"
# Note File # Note File
tokens._isNovel = False tokens._isNovel = False
@@ -427,7 +427,7 @@ def testCoreToken_HeaderFormat(mockGUI):
(Tokenizer.T_HEAD2, 1, "Prologue", None, Tokenizer.A_NONE), (Tokenizer.T_HEAD2, 1, "Prologue", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "##! Prologue\n\n" assert tokens.allMarkdown[-1] == "##! Prologue\n\n"
# END Test testCoreToken_HeaderFormat # END Test testCoreToken_HeaderFormat
@@ -446,11 +446,11 @@ def testCoreToken_MetaFormat(mockGUI):
(Tokenizer.T_COMMENT, 0, "A comment", None, Tokenizer.A_NONE), (Tokenizer.T_COMMENT, 0, "A comment", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "\n" assert tokens.allMarkdown[-1] == "\n"
tokens.setComments(True) tokens.setComments(True)
tokens.tokenizeText() tokens.tokenizeText()
assert tokens.theMarkdown[-1] == "% A comment\n\n" assert tokens.allMarkdown[-1] == "% A comment\n\n"
# Synopsis # Synopsis
tokens._text = "%synopsis: The synopsis\n" tokens._text = "%synopsis: The synopsis\n"
@@ -465,11 +465,11 @@ def testCoreToken_MetaFormat(mockGUI):
(Tokenizer.T_SYNOPSIS, 0, "The synopsis", None, Tokenizer.A_NONE), (Tokenizer.T_SYNOPSIS, 0, "The synopsis", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "\n" assert tokens.allMarkdown[-1] == "\n"
tokens.setSynopsis(True) tokens.setSynopsis(True)
tokens.tokenizeText() tokens.tokenizeText()
assert tokens.theMarkdown[-1] == "% synopsis: The synopsis\n\n" assert tokens.allMarkdown[-1] == "% synopsis: The synopsis\n\n"
# Short # Short
tokens.setSynopsis(False) tokens.setSynopsis(False)
@@ -479,11 +479,11 @@ def testCoreToken_MetaFormat(mockGUI):
(Tokenizer.T_SHORT, 0, "A short description", None, Tokenizer.A_NONE), (Tokenizer.T_SHORT, 0, "A short description", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "\n" assert tokens.allMarkdown[-1] == "\n"
tokens.setSynopsis(True) tokens.setSynopsis(True)
tokens.tokenizeText() tokens.tokenizeText()
assert tokens.theMarkdown[-1] == "% short: A short description\n\n" assert tokens.allMarkdown[-1] == "% short: A short description\n\n"
# Keyword # Keyword
tokens._text = "@char: Bod\n" tokens._text = "@char: Bod\n"
@@ -492,11 +492,11 @@ def testCoreToken_MetaFormat(mockGUI):
(Tokenizer.T_KEYWORD, 0, "char: Bod", None, Tokenizer.A_NONE), (Tokenizer.T_KEYWORD, 0, "char: Bod", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "\n" assert tokens.allMarkdown[-1] == "\n"
tokens.setKeywords(True) tokens.setKeywords(True)
tokens.tokenizeText() tokens.tokenizeText()
assert tokens.theMarkdown[-1] == "@char: Bod\n\n" assert tokens.allMarkdown[-1] == "@char: Bod\n\n"
tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n" tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n"
tokens.tokenizeText() tokens.tokenizeText()
@@ -509,7 +509,7 @@ def testCoreToken_MetaFormat(mockGUI):
(Tokenizer.T_KEYWORD, 0, "location: Europe", None, styBtm), (Tokenizer.T_KEYWORD, 0, "location: Europe", None, styBtm),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n" assert tokens.allMarkdown[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
# END Test testCoreToken_MetaFormat # END Test testCoreToken_MetaFormat
@@ -554,7 +554,7 @@ def testCoreToken_MarginFormat(mockGUI):
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == ( assert tokens.allMarkdown[-1] == (
"Some regular text\n\n" "Some regular text\n\n"
"Some left-aligned text\n\n" "Some left-aligned text\n\n"
"Some right-aligned text\n\n" "Some right-aligned text\n\n"
@@ -676,7 +676,7 @@ def testCoreToken_TextFormat(mockGUI):
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "Some plain text\non two lines\n\n\n\n" assert tokens.allMarkdown[-1] == "Some plain text\non two lines\n\n\n\n"
tokens.setBodyText(False) tokens.setBodyText(False)
tokens.tokenizeText() tokens.tokenizeText()
@@ -685,7 +685,7 @@ def testCoreToken_TextFormat(mockGUI):
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "\n\n\n" assert tokens.allMarkdown[-1] == "\n\n\n"
tokens.setBodyText(True) tokens.setBodyText(True)
# Text Emphasis # Text Emphasis
@@ -703,7 +703,7 @@ def testCoreToken_TextFormat(mockGUI):
), ),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "Some **bolded text** on this lines\n\n" assert tokens.allMarkdown[-1] == "Some **bolded text** on this lines\n\n"
tokens._text = "Some _italic text_ on this lines\n" tokens._text = "Some _italic text_ on this lines\n"
tokens.tokenizeText() tokens.tokenizeText()
@@ -719,7 +719,7 @@ def testCoreToken_TextFormat(mockGUI):
), ),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "Some _italic text_ on this lines\n\n" assert tokens.allMarkdown[-1] == "Some _italic text_ on this lines\n\n"
tokens._text = "Some **_bold italic text_** on this lines\n" tokens._text = "Some **_bold italic text_** on this lines\n"
tokens.tokenizeText() tokens.tokenizeText()
@@ -737,7 +737,7 @@ def testCoreToken_TextFormat(mockGUI):
), ),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "Some **_bold italic text_** on this lines\n\n" assert tokens.allMarkdown[-1] == "Some **_bold italic text_** on this lines\n\n"
tokens._text = "Some ~~strikethrough text~~ on this lines\n" tokens._text = "Some ~~strikethrough text~~ on this lines\n"
tokens.tokenizeText() tokens.tokenizeText()
@@ -753,7 +753,7 @@ def testCoreToken_TextFormat(mockGUI):
), ),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == "Some ~~strikethrough text~~ on this lines\n\n" assert tokens.allMarkdown[-1] == "Some ~~strikethrough text~~ on this lines\n\n"
tokens._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" tokens._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
tokens.tokenizeText() tokens.tokenizeText()
@@ -773,7 +773,7 @@ def testCoreToken_TextFormat(mockGUI):
), ),
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE), (Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
] ]
assert tokens.theMarkdown[-1] == ( assert tokens.allMarkdown[-1] == (
"Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n" "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n"
) )
+122 -122
View File
@@ -33,127 +33,127 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
"""Test the tokenizer and converter chain using the ToMarkdown """Test the tokenizer and converter chain using the ToMarkdown
class. class.
""" """
theProject = NWProject() project = NWProject()
theMD = ToMarkdown(theProject) toMD = ToMarkdown(project)
# Headers # Headers
# ======= # =======
theMD._isNovel = True toMD._isNovel = True
theMD._isNote = False toMD._isNote = False
theMD._isFirst = True toMD._isFirst = True
# Header 1 # Header 1
theMD._text = "# Partition\n" toMD._text = "# Partition\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "# Partition\n\n" assert toMD.result == "# Partition\n\n"
# Header 2 # Header 2
theMD._text = "## Chapter Title\n" toMD._text = "## Chapter Title\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "## Chapter Title\n\n" assert toMD.result == "## Chapter Title\n\n"
# Header 3 # Header 3
theMD._text = "### Scene Title\n" toMD._text = "### Scene Title\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "### Scene Title\n\n" assert toMD.result == "### Scene Title\n\n"
# Header 4 # Header 4
theMD._text = "#### Section Title\n" toMD._text = "#### Section Title\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "#### Section Title\n\n" assert toMD.result == "#### Section Title\n\n"
# Title # Title
theMD._text = "#! Title\n" toMD._text = "#! Title\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "# Title\n\n" assert toMD.result == "# Title\n\n"
# Unnumbered # Unnumbered
theMD._text = "##! Prologue\n" toMD._text = "##! Prologue\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "## Prologue\n\n" assert toMD.result == "## Prologue\n\n"
# Paragraphs # Paragraphs
# ========== # ==========
# Text for Extended Markdown # Text for Extended Markdown
theMD.setExtendedMarkdown() toMD.setExtendedMarkdown()
theMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == ( assert toMD.result == (
"Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n" "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n"
) )
# Text for Standard Markdown # Text for Standard Markdown
theMD.setStandardMarkdown() toMD.setStandardMarkdown()
theMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n" toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == ( assert toMD.result == (
"Some **nested bold and _italic_ and strikethrough text** here\n\n" "Some **nested bold and _italic_ and strikethrough text** here\n\n"
) )
# Text w/Hard Break # Text w/Hard Break
theMD._text = "Line one \nLine two \nLine three\n" toMD._text = "Line one \nLine two \nLine three\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "Line one \nLine two \nLine three\n\n" assert toMD.result == "Line one \nLine two \nLine three\n\n"
# Synopsis, Short # Synopsis, Short
theMD._text = "%synopsis: The synopsis ...\n" toMD._text = "%synopsis: The synopsis ...\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "" assert toMD.result == ""
theMD.setSynopsis(True) toMD.setSynopsis(True)
theMD._text = "%synopsis: The synopsis ...\n" toMD._text = "%synopsis: The synopsis ...\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "**Synopsis:** The synopsis ...\n\n" assert toMD.result == "**Synopsis:** The synopsis ...\n\n"
theMD.setSynopsis(True) toMD.setSynopsis(True)
theMD._text = "%short: A description ...\n" toMD._text = "%short: A description ...\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "**Short Description:** A description ...\n\n" assert toMD.result == "**Short Description:** A description ...\n\n"
# Comment # Comment
theMD._text = "% A comment ...\n" toMD._text = "% A comment ...\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "" assert toMD.result == ""
theMD.setComments(True) toMD.setComments(True)
theMD._text = "% A comment ...\n" toMD._text = "% A comment ...\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "**Comment:** A comment ...\n\n" assert toMD.result == "**Comment:** A comment ...\n\n"
# Keywords # Keywords
theMD._text = "@char: Bod, Jane\n" toMD._text = "@char: Bod, Jane\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "" assert toMD.result == ""
theMD.setKeywords(True) toMD.setKeywords(True)
theMD._text = "@char: Bod, Jane\n" toMD._text = "@char: Bod, Jane\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "**Characters:** Bod, Jane\n\n" assert toMD.result == "**Characters:** Bod, Jane\n\n"
# Multiple Keywords # Multiple Keywords
theMD.setKeywords(True) toMD.setKeywords(True)
theMD._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n" toMD._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n"
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == ( assert toMD.result == (
"## Chapter\n\n" "## Chapter\n\n"
"**Point of View:** Bod \n" "**Point of View:** Bod \n"
"**Plot:** Main \n" "**Plot:** Main \n"
@@ -166,49 +166,49 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
@pytest.mark.core @pytest.mark.core
def testCoreToMarkdown_ConvertDirect(mockGUI): def testCoreToMarkdown_ConvertDirect(mockGUI):
"""Test the converter directly using the ToMarkdown class.""" """Test the converter directly using the ToMarkdown class."""
theProject = NWProject() project = NWProject()
theMD = ToMarkdown(theProject) toMD = ToMarkdown(project)
theMD._isNovel = True toMD._isNovel = True
theMD._isNote = False toMD._isNote = False
# Special Titles # Special Titles
# ============== # ==============
# Title # Title
theMD._tokens = [ toMD._tokens = [
(theMD.T_TITLE, 1, "A Title", None, theMD.A_PBB | theMD.A_CENTRE), (toMD.T_TITLE, 1, "A Title", None, toMD.A_PBB | toMD.A_CENTRE),
(theMD.T_EMPTY, 1, "", None, theMD.A_NONE), (toMD.T_EMPTY, 1, "", None, toMD.A_NONE),
] ]
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "# A Title\n\n" assert toMD.result == "# A Title\n\n"
# Unnumbered # Unnumbered
theMD._tokens = [ toMD._tokens = [
(theMD.T_UNNUM, 1, "Prologue", None, theMD.A_PBB), (toMD.T_UNNUM, 1, "Prologue", None, toMD.A_PBB),
(theMD.T_EMPTY, 1, "", None, theMD.A_NONE), (toMD.T_EMPTY, 1, "", None, toMD.A_NONE),
] ]
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "## Prologue\n\n" assert toMD.result == "## Prologue\n\n"
# Separators # Separators
# ========== # ==========
# Separator # Separator
theMD._tokens = [ toMD._tokens = [
(theMD.T_SEP, 1, "* * *", None, theMD.A_CENTRE), (toMD.T_SEP, 1, "* * *", None, toMD.A_CENTRE),
(theMD.T_EMPTY, 1, "", None, theMD.A_NONE), (toMD.T_EMPTY, 1, "", None, toMD.A_NONE),
] ]
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "* * *\n\n" assert toMD.result == "* * *\n\n"
# Skip # Skip
theMD._tokens = [ toMD._tokens = [
(theMD.T_SKIP, 1, "", None, theMD.A_NONE), (toMD.T_SKIP, 1, "", None, toMD.A_NONE),
(theMD.T_EMPTY, 1, "", None, theMD.A_NONE), (toMD.T_EMPTY, 1, "", None, toMD.A_NONE),
] ]
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == "\n\n\n" assert toMD.result == "\n\n\n"
# END Test testCoreToMarkdown_ConvertDirect # END Test testCoreToMarkdown_ConvertDirect
@@ -216,9 +216,9 @@ def testCoreToMarkdown_ConvertDirect(mockGUI):
@pytest.mark.core @pytest.mark.core
def testCoreToMarkdown_Complex(mockGUI, fncPath): def testCoreToMarkdown_Complex(mockGUI, fncPath):
"""Test the save method of the ToMarkdown class.""" """Test the save method of the ToMarkdown class."""
theProject = NWProject() project = NWProject()
theMD = ToMarkdown(theProject) toMD = ToMarkdown(project)
theMD._isNovel = True toMD._isNovel = True
# Build Project # Build Project
# ============= # =============
@@ -243,23 +243,23 @@ def testCoreToMarkdown_Complex(mockGUI, fncPath):
] ]
for i in range(len(docText)): for i in range(len(docText)):
theMD._text = docText[i] toMD._text = docText[i]
theMD.doPreProcessing() toMD.doPreProcessing()
theMD.tokenizeText() toMD.tokenizeText()
theMD.doConvert() toMD.doConvert()
assert theMD.theResult == resText[i] assert toMD.result == resText[i]
assert theMD.fullMD == resText assert toMD.fullMD == resText
assert theMD.getFullResultSize() == len("".join(resText)) assert toMD.getFullResultSize() == len("".join(resText))
theMD.replaceTabs(nSpaces=4, spaceChar=" ") toMD.replaceTabs(nSpaces=4, spaceChar=" ")
resText[6] = "#### A Section\n\n More text in scene two.\n\n" resText[6] = "#### A Section\n\n More text in scene two.\n\n"
# Check File # Check File
# ========== # ==========
saveFile = fncPath / "outFile.md" saveFile = fncPath / "outFile.md"
theMD.saveMarkdown(saveFile) toMD.saveMarkdown(saveFile)
assert readFile(saveFile) == "".join(resText) assert readFile(saveFile) == "".join(resText)
# END Test testCoreToHtml_Complex # END Test testCoreToHtml_Complex
@@ -268,12 +268,12 @@ def testCoreToMarkdown_Complex(mockGUI, fncPath):
@pytest.mark.core @pytest.mark.core
def testCoreToMarkdown_Format(mockGUI): def testCoreToMarkdown_Format(mockGUI):
"""Test all the formatters for the ToMarkdown class.""" """Test all the formatters for the ToMarkdown class."""
theProject = NWProject() project = NWProject()
theMD = ToMarkdown(theProject) toMD = ToMarkdown(project)
assert theMD._formatKeywords("", theMD.A_NONE) == "" assert toMD._formatKeywords("", toMD.A_NONE) == ""
assert theMD._formatKeywords("tag: Jane", theMD.A_NONE) == "**Tag:** Jane\n\n" assert toMD._formatKeywords("tag: Jane", toMD.A_NONE) == "**Tag:** Jane\n\n"
assert theMD._formatKeywords("tag: Jane, John", theMD.A_NONE) == "**Tag:** Jane, John\n\n" assert toMD._formatKeywords("tag: Jane, John", toMD.A_NONE) == "**Tag:** Jane, John\n\n"
assert theMD._formatKeywords("tag: Jane", theMD.A_Z_BTMMRG) == "**Tag:** Jane \n" assert toMD._formatKeywords("tag: Jane", toMD.A_Z_BTMMRG) == "**Tag:** Jane \n"
# END Test testCoreToMarkdown_Format # END Test testCoreToMarkdown_Format
+30 -30
View File
@@ -134,9 +134,9 @@ def testCoreToOdt_TextFormatting(mockGUI):
"Heading_20_1", "Heading_20_2", "Heading_20_3", "Heading_20_4", "Header", "Heading_20_1", "Heading_20_2", "Heading_20_3", "Heading_20_4", "Header",
] ]
theKey = "071d6b2e4764749f8c78d3c1ab9099fa04c07d2d53fd3de61eb1bdf1cb4845c3" key = "071d6b2e4764749f8c78d3c1ab9099fa04c07d2d53fd3de61eb1bdf1cb4845c3"
assert odt._autoPara[theKey][0] == "P1" assert odt._autoPara[key][0] == "P1"
assert isinstance(odt._autoPara[theKey][1], ODTParagraphStyle) assert isinstance(odt._autoPara[key][1], ODTParagraphStyle)
# Paragraph Formatting # Paragraph Formatting
# ==================== # ====================
@@ -624,48 +624,48 @@ def testCoreToOdt_ConvertDirect(mockGUI):
"""Test the converter directly using the ToOdt class to reach some """Test the converter directly using the ToOdt class to reach some
otherwise hard to reach conditions. otherwise hard to reach conditions.
""" """
theProject = NWProject() project = NWProject()
theDoc = ToOdt(theProject, isFlat=True) doc = ToOdt(project, isFlat=True)
theDoc._isNovel = True doc._isNovel = True
# Justified # Justified
theDoc = ToOdt(theProject, isFlat=True) doc = ToOdt(project, isFlat=True)
theDoc._tokens = [ doc._tokens = [
(theDoc.T_TEXT, 1, "This is a paragraph", [], theDoc.A_JUSTIFY), (doc.T_TEXT, 1, "This is a paragraph", [], doc.A_JUSTIFY),
(theDoc.T_EMPTY, 1, "", None, theDoc.A_NONE), (doc.T_EMPTY, 1, "", None, doc.A_NONE),
] ]
theDoc.initDocument() doc.initDocument()
theDoc.doConvert() doc.doConvert()
theDoc.closeDocument() doc.closeDocument()
assert ( assert (
'<style:style style:name="P1" style:family="paragraph" ' '<style:style style:name="P1" style:family="paragraph" '
'style:parent-style-name="Text_20_body">' 'style:parent-style-name="Text_20_body">'
'<style:paragraph-properties fo:text-align="justify" />' '<style:paragraph-properties fo:text-align="justify" />'
'</style:style>' '</style:style>'
) in xmlToText(theDoc._xAuto) ) in xmlToText(doc._xAuto)
assert xmlToText(theDoc._xText) == ( assert xmlToText(doc._xText) == (
'<office:text>' '<office:text>'
'<text:p text:style-name="P1">This is a paragraph</text:p>' '<text:p text:style-name="P1">This is a paragraph</text:p>'
'</office:text>' '</office:text>'
) )
# Page Break After # Page Break After
theDoc = ToOdt(theProject, isFlat=True) doc = ToOdt(project, isFlat=True)
theDoc._tokens = [ doc._tokens = [
(theDoc.T_TEXT, 1, "This is a paragraph", [], theDoc.A_PBA), (doc.T_TEXT, 1, "This is a paragraph", [], doc.A_PBA),
(theDoc.T_EMPTY, 1, "", None, theDoc.A_NONE), (doc.T_EMPTY, 1, "", None, doc.A_NONE),
] ]
theDoc.initDocument() doc.initDocument()
theDoc.doConvert() doc.doConvert()
theDoc.closeDocument() doc.closeDocument()
assert ( assert (
'<style:style style:name="P1" style:family="paragraph" ' '<style:style style:name="P1" style:family="paragraph" '
'style:parent-style-name="Text_20_body">' 'style:parent-style-name="Text_20_body">'
'<style:paragraph-properties fo:break-after="page" />' '<style:paragraph-properties fo:break-after="page" />'
'</style:style>' '</style:style>'
) in xmlToText(theDoc._xAuto) ) in xmlToText(doc._xAuto)
assert xmlToText(theDoc._xText) == ( assert xmlToText(doc._xText) == (
'<office:text>' '<office:text>'
'<text:p text:style-name="P1">This is a paragraph</text:p>' '<text:p text:style-name="P1">This is a paragraph</text:p>'
'</office:text>' '</office:text>'
@@ -767,12 +767,12 @@ def testCoreToOdt_SaveFull(mockGUI, fncPath, tstPaths):
extaxtTo = tstPaths.outDir / "coreToOdt_SaveFull" extaxtTo = tstPaths.outDir / "coreToOdt_SaveFull"
with zipfile.ZipFile(fullFile, mode="r") as theZip: with zipfile.ZipFile(fullFile, mode="r") as zipObj:
theZip.extract("META-INF/manifest.xml", extaxtTo) zipObj.extract("META-INF/manifest.xml", extaxtTo)
theZip.extract("settings.xml", extaxtTo) zipObj.extract("settings.xml", extaxtTo)
theZip.extract("content.xml", extaxtTo) zipObj.extract("content.xml", extaxtTo)
theZip.extract("meta.xml", extaxtTo) zipObj.extract("meta.xml", extaxtTo)
theZip.extract("styles.xml", extaxtTo) zipObj.extract("styles.xml", extaxtTo)
maniOut = tstPaths.outDir / "coreToOdt_SaveFull" / "META-INF" / "manifest.xml" maniOut = tstPaths.outDir / "coreToOdt_SaveFull" / "META-INF" / "manifest.xml"
settOut = tstPaths.outDir / "coreToOdt_SaveFull" / "settings.xml" settOut = tstPaths.outDir / "coreToOdt_SaveFull" / "settings.xml"
+172 -172
View File
@@ -39,23 +39,23 @@ from novelwriter.core.project import NWProject
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def mockItems(mockGUI, mockRnd): def mockItems(mockGUI, mockRnd):
"""Create a list of mock items.""" """Create a list of mock items."""
theProject = NWProject() project = NWProject()
itemA = NWItem(theProject, "a000000000001") itemA = NWItem(project, "a000000000001")
itemA._name = "Novel" itemA._name = "Novel"
itemA._parent = None itemA._parent = None
itemA._type = nwItemType.ROOT itemA._type = nwItemType.ROOT
itemA._class = nwItemClass.NOVEL itemA._class = nwItemClass.NOVEL
itemA._expanded = True itemA._expanded = True
itemB = NWItem(theProject, "b000000000001") itemB = NWItem(project, "b000000000001")
itemB._name = "Act One" itemB._name = "Act One"
itemB._parent = "a000000000001" itemB._parent = "a000000000001"
itemB._type = nwItemType.FOLDER itemB._type = nwItemType.FOLDER
itemB._class = nwItemClass.NOVEL itemB._class = nwItemClass.NOVEL
itemB._expanded = True itemB._expanded = True
itemC = NWItem(theProject, "c000000000001") itemC = NWItem(project, "c000000000001")
itemC._name = "Chapter One" itemC._name = "Chapter One"
itemC._parent = "b000000000001" itemC._parent = "b000000000001"
itemC._type = nwItemType.FILE itemC._type = nwItemType.FILE
@@ -65,7 +65,7 @@ def mockItems(mockGUI, mockRnd):
itemC._wordCount = 50 itemC._wordCount = 50
itemC._paraCount = 2 itemC._paraCount = 2
itemD = NWItem(theProject, "c000000000002") itemD = NWItem(project, "c000000000002")
itemD._name = "Scene One" itemD._name = "Scene One"
itemD._parent = "b000000000001" itemD._parent = "b000000000001"
itemD._type = nwItemType.FILE itemD._type = nwItemType.FILE
@@ -75,28 +75,28 @@ def mockItems(mockGUI, mockRnd):
itemD._wordCount = 500 itemD._wordCount = 500
itemD._paraCount = 20 itemD._paraCount = 20
itemE = NWItem(theProject, "a000000000002") itemE = NWItem(project, "a000000000002")
itemE._name = "Outtakes" itemE._name = "Outtakes"
itemE._parent = None itemE._parent = None
itemE._type = nwItemType.ROOT itemE._type = nwItemType.ROOT
itemE._class = nwItemClass.ARCHIVE itemE._class = nwItemClass.ARCHIVE
itemE._expanded = False itemE._expanded = False
itemF = NWItem(theProject, "a000000000003") itemF = NWItem(project, "a000000000003")
itemF._name = "Trash" itemF._name = "Trash"
itemF._parent = None itemF._parent = None
itemF._type = nwItemType.ROOT itemF._type = nwItemType.ROOT
itemF._class = nwItemClass.TRASH itemF._class = nwItemClass.TRASH
itemF._expanded = False itemF._expanded = False
itemG = NWItem(theProject, "a000000000004") itemG = NWItem(project, "a000000000004")
itemG._name = "Characters" itemG._name = "Characters"
itemG._parent = None itemG._parent = None
itemG._type = nwItemType.ROOT itemG._type = nwItemType.ROOT
itemG._class = nwItemClass.CHARACTER itemG._class = nwItemClass.CHARACTER
itemG._expanded = True itemG._expanded = True
itemH = NWItem(theProject, "b000000000002") itemH = NWItem(project, "b000000000002")
itemH._name = "Jane Doe" itemH._name = "Jane Doe"
itemH._parent = "a000000000004" itemH._parent = "a000000000004"
itemH._type = nwItemType.FILE itemH._type = nwItemType.FILE
@@ -112,126 +112,126 @@ def mockItems(mockGUI, mockRnd):
@pytest.mark.core @pytest.mark.core
def testCoreTree_BuildTree(mockGUI, mockItems): def testCoreTree_BuildTree(mockGUI, mockItems):
"""Test building a project tree from a list of items.""" """Test building a project tree from a list of items."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
# Check that tree is empty (calls NWTree.__bool__) # Check that tree is empty (calls NWTree.__bool__)
assert bool(theTree) is False assert bool(tree) is False
# Check for archive and trash folders # Check for archive and trash folders
assert theTree.trashRoot is None assert tree.trashRoot is None
aHandles = [] aHandles = []
for nwItem in mockItems: for nwItem in mockItems:
aHandles.append(nwItem.itemHandle) aHandles.append(nwItem.itemHandle)
assert theTree.append(nwItem) is True assert tree.append(nwItem) is True
assert theTree.updateItemData(nwItem.itemHandle) is True assert tree.updateItemData(nwItem.itemHandle) is True
assert theTree._changed is True assert tree._changed is True
# Check that tree is not empty (calls __bool__) # Check that tree is not empty (calls __bool__)
assert bool(theTree) is True assert bool(tree) is True
# Check the number of elements (calls __len__) # Check the number of elements (calls __len__)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
# Check that we have the correct handles # Check that we have the correct handles
assert theTree.handles() == aHandles assert tree.handles() == aHandles
# Check by iterator (calls __iter__, __next__ and __getitem__) # Check by iterator (calls __iter__, __next__ and __getitem__)
for theItem, theHandle in zip(theTree, aHandles): for item, handle in zip(tree, aHandles):
assert theItem.itemHandle == theHandle assert item.itemHandle == handle
# Trash Folder # Trash Folder
# ============ # ============
# Check that we have the correct archive and trash folders # Check that we have the correct archive and trash folders
assert theTree.trashRoot == "a000000000003" assert tree.trashRoot == "a000000000003"
assert theTree.findRoot(nwItemClass.ARCHIVE) == "a000000000002" assert tree.findRoot(nwItemClass.ARCHIVE) == "a000000000002"
assert theTree.isTrash("a000000000003") is True assert tree.isTrash("a000000000003") is True
# Check that we have the root classes # Check that we have the root classes
assert theTree.rootClasses() == { assert tree.rootClasses() == {
nwItemClass.NOVEL, nwItemClass.CHARACTER, nwItemClass.ARCHIVE, nwItemClass.TRASH nwItemClass.NOVEL, nwItemClass.CHARACTER, nwItemClass.ARCHIVE, nwItemClass.TRASH
} }
# Check the isTrash function # Check the isTrash function
assert theTree.isTrash("0000000000000") is True # Doesn't exist assert tree.isTrash("0000000000000") is True # Doesn't exist
assert theTree.isTrash("a000000000003") is True # This the trash folder assert tree.isTrash("a000000000003") is True # This the trash folder
theTree["a000000000003"].setClass(nwItemClass.NO_CLASS) # type: ignore tree["a000000000003"].setClass(nwItemClass.NO_CLASS) # type: ignore
assert theTree.isTrash("a000000000003") is True # This is still trash assert tree.isTrash("a000000000003") is True # This is still trash
theTree["a000000000003"].setClass(nwItemClass.TRASH) # type: ignore tree["a000000000003"].setClass(nwItemClass.TRASH) # type: ignore
assert theTree.isTrash("b000000000002") is False # This is not trash assert tree.isTrash("b000000000002") is False # This is not trash
value = theTree["b000000000002"].itemParent # type: ignore value = tree["b000000000002"].itemParent # type: ignore
theTree["b000000000002"].setParent("a000000000003") # type: ignore tree["b000000000002"].setParent("a000000000003") # type: ignore
assert theTree.isTrash("b000000000002") is True # This is in trash assert tree.isTrash("b000000000002") is True # This is in trash
theTree["b000000000002"].setParent(value) # type: ignore tree["b000000000002"].setParent(value) # type: ignore
value = theTree["b000000000002"].itemRoot # type: ignore value = tree["b000000000002"].itemRoot # type: ignore
theTree["b000000000002"].setRoot("a000000000003") # type: ignore tree["b000000000002"].setRoot("a000000000003") # type: ignore
assert theTree.isTrash("b000000000002") is True # This is in trash assert tree.isTrash("b000000000002") is True # This is in trash
theTree["b000000000002"].setRoot(value) # type: ignore tree["b000000000002"].setRoot(value) # type: ignore
# Try to add another trash folder # Try to add another trash folder
itemT = NWItem(theProject, "1111111111111") itemT = NWItem(project, "1111111111111")
itemT._name = "Trash" itemT._name = "Trash"
itemT._type = nwItemType.ROOT itemT._type = nwItemType.ROOT
itemT._class = nwItemClass.TRASH itemT._class = nwItemClass.TRASH
itemT._expanded = False itemT._expanded = False
assert theTree.append(itemT) is False assert tree.append(itemT) is False
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
# Create or Add Items # Create or Add Items
# =================== # ===================
# Create a new item, but with invalid parent # Create a new item, but with invalid parent
assert theTree.create("New File", "blabla", nwItemType.FILE, nwItemClass.NO_CLASS) is None assert tree.create("New File", "blabla", nwItemType.FILE, nwItemClass.NO_CLASS) is None
# Create a new, valid item # Create a new, valid item
nHandle = theTree.create("New File", "b000000000001", nwItemType.FILE, nwItemClass.NO_CLASS) nHandle = tree.create("New File", "b000000000001", nwItemType.FILE, nwItemClass.NO_CLASS)
assert isHandle(nHandle) assert isHandle(nHandle)
assert nHandle == "0000000000000" assert nHandle == "0000000000000"
# The new item should be the last item in the tree # The new item should be the last item in the tree
theList = theTree.handles() handles = tree.handles()
assert theList[-1] == nHandle assert handles[-1] == nHandle
# Retrieve the item # Retrieve the item
itemT = theTree[nHandle] itemT = tree[nHandle]
assert isinstance(itemT, NWItem) assert isinstance(itemT, NWItem)
assert len(theTree) == len(mockItems) + 1 assert len(tree) == len(mockItems) + 1
# We should not be allowed to add the item again # We should not be allowed to add the item again
assert theTree.append(itemT) is False assert tree.append(itemT) is False
assert len(theTree) == len(mockItems) + 1 assert len(tree) == len(mockItems) + 1
# Create an invalid item to add, which will be rejected # Create an invalid item to add, which will be rejected
itemU = NWItem.duplicate(itemT, "blabla") itemU = NWItem.duplicate(itemT, "blabla")
assert theTree.append(itemU) is False assert tree.append(itemU) is False
assert len(theTree) == len(mockItems) + 1 assert len(tree) == len(mockItems) + 1
# Create a new root, but with a parent set anyway (the parent should be ignored) # Create a new root, but with a parent set anyway (the parent should be ignored)
zHandle = theTree.create("Custom", "a000000000001", nwItemType.ROOT, nwItemClass.CUSTOM) zHandle = tree.create("Custom", "a000000000001", nwItemType.ROOT, nwItemClass.CUSTOM)
assert isinstance(zHandle, str) assert isinstance(zHandle, str)
itemZ = theTree[zHandle] itemZ = tree[zHandle]
assert isinstance(itemZ, NWItem) assert isinstance(itemZ, NWItem)
assert itemZ.itemParent is None assert itemZ.itemParent is None
del theTree[zHandle] del tree[zHandle]
# Duplicate Items # Duplicate Items
# =============== # ===============
# Duplicate a non-existing item # Duplicate a non-existing item
assert theTree.duplicate("blabla") is None assert tree.duplicate("blabla") is None
# Duplicate the new item # Duplicate the new item
itemV = theTree.duplicate(nHandle) itemV = tree.duplicate(nHandle)
assert isinstance(itemV, NWItem) assert isinstance(itemV, NWItem)
assert len(theTree) == len(mockItems) + 2 assert len(tree) == len(mockItems) + 2
dHandle = itemV.itemHandle dHandle = itemV.itemHandle
assert dHandle == "0000000000002" assert dHandle == "0000000000002"
@@ -240,28 +240,28 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
# ============ # ============
# Delete a non-existing item # Delete a non-existing item
del theTree["stuff"] del tree["stuff"]
assert len(theTree) == len(mockItems) + 2 assert len(tree) == len(mockItems) + 2
# Delete the last items # Delete the last items
del theTree[nHandle] del tree[nHandle]
del theTree[dHandle] del tree[dHandle]
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
assert nHandle not in theTree assert nHandle not in tree
# Delete the Novel, Archive and Trash folders # Delete the Novel, Archive and Trash folders
del theTree["a000000000001"] del tree["a000000000001"]
assert len(theTree) == len(mockItems) - 1 assert len(tree) == len(mockItems) - 1
assert "a000000000001" not in theTree assert "a000000000001" not in tree
del theTree["a000000000002"] del tree["a000000000002"]
assert len(theTree) == len(mockItems) - 2 assert len(tree) == len(mockItems) - 2
assert "a000000000002" not in theTree assert "a000000000002" not in tree
del theTree["a000000000003"] del tree["a000000000003"]
assert len(theTree) == len(mockItems) - 3 assert len(tree) == len(mockItems) - 3
assert "a000000000003" not in theTree assert "a000000000003" not in tree
assert theTree.trashRoot is None assert tree.trashRoot is None
# END Test testCoreTree_BuildTree # END Test testCoreTree_BuildTree
@@ -269,28 +269,28 @@ def testCoreTree_BuildTree(mockGUI, mockItems):
@pytest.mark.core @pytest.mark.core
def testCoreTree_PackUnpack(mockGUI, mockItems): def testCoreTree_PackUnpack(mockGUI, mockItems):
"""Test packing and unpacking data.""" """Test packing and unpacking data."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
aHandles = [] aHandles = []
for nwItem in mockItems: for nwItem in mockItems:
aHandles.append(nwItem.itemHandle) aHandles.append(nwItem.itemHandle)
theTree.append(nwItem) tree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle) tree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
# Pack # Pack
tree = theTree.pack() packed = tree.pack()
for i, nwItem in enumerate(mockItems): for i, nwItem in enumerate(mockItems):
assert tree[i]["itemAttr"]["handle"] == nwItem.itemHandle assert packed[i]["itemAttr"]["handle"] == nwItem.itemHandle
# Unpack # Unpack
theTree.clear() tree.clear()
assert len(theTree) == 0 assert len(tree) == 0
assert theTree.handles() == [] assert tree.handles() == []
theTree.unpack(tree) tree.unpack(packed)
assert theTree.handles() == aHandles assert tree.handles() == aHandles
# END Test testCoreTree_PackUnpack # END Test testCoreTree_PackUnpack
@@ -298,35 +298,35 @@ def testCoreTree_PackUnpack(mockGUI, mockItems):
@pytest.mark.core @pytest.mark.core
def testCoreTree_CheckConsistency(caplog: pytest.LogCaptureFixture, mockGUI, fncPath, mockRnd): def testCoreTree_CheckConsistency(caplog: pytest.LogCaptureFixture, mockGUI, fncPath, mockRnd):
"""Check the project consistency.""" """Check the project consistency."""
theProject = NWProject() project = NWProject()
buildTestProject(theProject, fncPath) buildTestProject(project, fncPath)
# By default, all is well # By default, all is well
caplog.clear() caplog.clear()
assert theProject.tree.checkConsistency("Recovered") == (0, 0) assert project.tree.checkConsistency("Recovered") == (0, 0)
assert all(m.endswith("OK") for m in caplog.messages) assert all(m.endswith("OK") for m in caplog.messages)
# Give the scene file an unknown parent # Give the scene file an unknown parent
caplog.clear() caplog.clear()
theProject.tree[C.hSceneDoc].setParent(C.hInvalid) # type: ignore project.tree[C.hSceneDoc].setParent(C.hInvalid) # type: ignore
assert theProject.tree.checkConsistency("Recovered") == (1, 1) assert project.tree.checkConsistency("Recovered") == (1, 1)
assert f"'{C.hSceneDoc}' ... ERROR" in caplog.text assert f"'{C.hSceneDoc}' ... ERROR" in caplog.text
# The scene file should have been added back to its home # The scene file should have been added back to its home
itemS = theProject.tree[C.hSceneDoc] itemS = project.tree[C.hSceneDoc]
assert isinstance(itemS, NWItem) assert isinstance(itemS, NWItem)
assert itemS.itemParent == C.hChapterDir assert itemS.itemParent == C.hChapterDir
# Create a new file with no meta data, and let the function handle it as orphaned # Create a new file with no meta data, and let the function handle it as orphaned
xHandle = "0123456789abc" xHandle = "0123456789abc"
contentPath = theProject.storage.contentPath contentPath = project.storage.contentPath
assert isinstance(contentPath, Path) assert isinstance(contentPath, Path)
assert contentPath == fncPath / "content" assert contentPath == fncPath / "content"
(contentPath / f"{xHandle}.nwd").write_text("### Stuff", encoding="utf-8") (contentPath / f"{xHandle}.nwd").write_text("### Stuff", encoding="utf-8")
assert theProject.tree.checkConsistency("Recovered") == (1, 1) assert project.tree.checkConsistency("Recovered") == (1, 1)
assert xHandle in theProject.tree assert xHandle in project.tree
itemX = theProject.tree[xHandle] itemX = project.tree[xHandle]
assert isinstance(itemX, NWItem) assert isinstance(itemX, NWItem)
# It should by default be added as a Novel file # It should by default be added as a Novel file
@@ -339,13 +339,13 @@ def testCoreTree_CheckConsistency(caplog: pytest.LogCaptureFixture, mockGUI, fnc
itemX.setClass(nwItemClass.OBJECT) itemX.setClass(nwItemClass.OBJECT)
itemX.setName("Stuff") itemX.setName("Stuff")
itemX.setParent(C.hInvalid) itemX.setParent(C.hInvalid)
theProject.storage.getDocument(xHandle).writeDocument("### Stuff") # This adds meta data project.storage.getDocument(xHandle).writeDocument("### Stuff") # This adds meta data
# Remove the item in the project, and re-run the consistency check # Remove the item in the project, and re-run the consistency check
del theProject.tree[xHandle] del project.tree[xHandle]
assert theProject.tree.checkConsistency("Recovered") == (1, 1) assert project.tree.checkConsistency("Recovered") == (1, 1)
assert xHandle in theProject.tree assert xHandle in project.tree
itemX = theProject.tree[xHandle] itemX = project.tree[xHandle]
assert isinstance(itemX, NWItem) assert isinstance(itemX, NWItem)
# It should again be added as a Novel file # It should again be added as a Novel file
@@ -355,11 +355,11 @@ def testCoreTree_CheckConsistency(caplog: pytest.LogCaptureFixture, mockGUI, fnc
assert itemX.itemName == "[Recovered] Stuff" assert itemX.itemName == "[Recovered] Stuff"
# If the tree is empty, a new root folder is created # If the tree is empty, a new root folder is created
theProject.tree.clear() project.tree.clear()
assert theProject.tree.checkConsistency("Recovered") == (4, 4) assert project.tree.checkConsistency("Recovered") == (4, 4)
assert len(theProject.tree) == 5 assert len(project.tree) == 5
nHandle = theProject.tree.findRoot(nwItemClass.NOVEL) nHandle = project.tree.findRoot(nwItemClass.NOVEL)
assert theProject.tree[nHandle].itemName == "Recovered" # type: ignore assert project.tree[nHandle].itemName == "Recovered" # type: ignore
# END Test testCoreTree_CheckConsistency # END Test testCoreTree_CheckConsistency
@@ -367,58 +367,58 @@ def testCoreTree_CheckConsistency(caplog: pytest.LogCaptureFixture, mockGUI, fnc
@pytest.mark.core @pytest.mark.core
def testCoreTree_Methods(monkeypatch, mockGUI, mockItems): def testCoreTree_Methods(monkeypatch, mockGUI, mockItems):
"""Test various class methods.""" """Test various class methods."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
for nwItem in mockItems: for nwItem in mockItems:
theTree.append(nwItem) tree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle) tree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
# Update item data, nonsense handle # Update item data, nonsense handle
assert theTree.updateItemData("stuff") is False assert tree.updateItemData("stuff") is False
# Update item data, invalid item parent # Update item data, invalid item parent
corrParent = theTree["b000000000001"].itemParent # type: ignore corrParent = tree["b000000000001"].itemParent # type: ignore
theTree["b000000000001"].setParent("0000000000000") # type: ignore tree["b000000000001"].setParent("0000000000000") # type: ignore
assert theTree.updateItemData("b000000000001") is False assert tree.updateItemData("b000000000001") is False
# Update item data, valid item parent # Update item data, valid item parent
theTree["b000000000001"].setParent(corrParent) # type: ignore tree["b000000000001"].setParent(corrParent) # type: ignore
assert theTree.updateItemData("b000000000001") is True assert tree.updateItemData("b000000000001") is True
# Update item data, root is unreachable # Update item data, root is unreachable
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.tree.MAX_DEPTH", 0) mp.setattr("novelwriter.core.tree.MAX_DEPTH", 0)
with pytest.raises(RecursionError): with pytest.raises(RecursionError):
theTree.updateItemData("b000000000001") tree.updateItemData("b000000000001")
# Check type # Check type
assert theTree.checkType("blabla", nwItemType.FILE) is False assert tree.checkType("blabla", nwItemType.FILE) is False
assert theTree.checkType("b000000000001", nwItemType.FILE) is False assert tree.checkType("b000000000001", nwItemType.FILE) is False
assert theTree.checkType("c000000000001", nwItemType.FILE) is True assert tree.checkType("c000000000001", nwItemType.FILE) is True
# Root item lookup # Root item lookup
assert theTree.findRoot(nwItemClass.WORLD) is None assert tree.findRoot(nwItemClass.WORLD) is None
assert theTree.findRoot(nwItemClass.NOVEL) == "a000000000001" assert tree.findRoot(nwItemClass.NOVEL) == "a000000000001"
assert theTree.findRoot(nwItemClass.CHARACTER) == "a000000000004" assert tree.findRoot(nwItemClass.CHARACTER) == "a000000000004"
# Iter roots # Iter roots
roots = list(theTree.iterRoots(None)) roots = list(tree.iterRoots(None))
assert roots[0][0] == "a000000000001" assert roots[0][0] == "a000000000001"
assert roots[1][0] == "a000000000002" assert roots[1][0] == "a000000000002"
assert roots[2][0] == "a000000000003" assert roots[2][0] == "a000000000003"
assert roots[3][0] == "a000000000004" assert roots[3][0] == "a000000000004"
# Add a fake item to root and check that it can handle it # Add a fake item to root and check that it can handle it
theTree._roots["0000000000000"] = NWItem(theProject, "0000000000000") tree._roots["0000000000000"] = NWItem(project, "0000000000000")
assert theTree.findRoot(nwItemClass.WORLD) is None assert tree.findRoot(nwItemClass.WORLD) is None
del theTree._roots["0000000000000"] del tree._roots["0000000000000"]
# Get item path # Get item path
assert theTree.getItemPath("stuff") == [] assert tree.getItemPath("stuff") == []
assert theTree.getItemPath("c000000000001") == [ assert tree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001", "a000000000001" "c000000000001", "b000000000001", "a000000000001"
] ]
@@ -426,16 +426,16 @@ def testCoreTree_Methods(monkeypatch, mockGUI, mockItems):
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.tree.MAX_DEPTH", 0) mp.setattr("novelwriter.core.tree.MAX_DEPTH", 0)
with pytest.raises(RecursionError): with pytest.raises(RecursionError):
theTree.getItemPath("c000000000001") tree.getItemPath("c000000000001")
# Break the folder parent handle # Break the folder parent handle
theTree["b000000000001"]._parent = "stuff" # type: ignore tree["b000000000001"]._parent = "stuff" # type: ignore
assert theTree.getItemPath("c000000000001") == [ assert tree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001" "c000000000001", "b000000000001"
] ]
theTree["b000000000001"]._parent = "a000000000001" # type: ignore tree["b000000000001"]._parent = "a000000000001" # type: ignore
assert theTree.getItemPath("c000000000001") == [ assert tree.getItemPath("c000000000001") == [
"c000000000001", "b000000000001", "a000000000001" "c000000000001", "b000000000001", "a000000000001"
] ]
@@ -446,26 +446,26 @@ def testCoreTree_Methods(monkeypatch, mockGUI, mockItems):
def testCoreTree_MakeHandles(mockGUI): def testCoreTree_MakeHandles(mockGUI):
"""Test generating item handles.""" """Test generating item handles."""
random.seed(42) random.seed(42)
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
handles = ["1c803a3b1799d", "bdd6406671ad1", "3eb1346685257", "23b8c392456de"] handles = ["1c803a3b1799d", "bdd6406671ad1", "3eb1346685257", "23b8c392456de"]
random.seed(42) random.seed(42)
tHandle = theTree._makeHandle() tHandle = tree._makeHandle()
assert tHandle == handles[0] assert tHandle == handles[0]
theTree._tree[handles[0]] = None # type: ignore tree._tree[handles[0]] = None # type: ignore
# Add the next in line to the project to force duplicate # Add the next in line to the project to force duplicate
theTree._tree[handles[1]] = None # type: ignore tree._tree[handles[1]] = None # type: ignore
tHandle = theTree._makeHandle() tHandle = tree._makeHandle()
assert tHandle == handles[2] assert tHandle == handles[2]
theTree._tree[handles[2]] = None # type: ignore tree._tree[handles[2]] = None # type: ignore
# Reset the seed to force collissions, which should still end up # Reset the seed to force collissions, which should still end up
# returning the next handle in the sequence # returning the next handle in the sequence
random.seed(42) random.seed(42)
tHandle = theTree._makeHandle() tHandle = tree._makeHandle()
assert tHandle == handles[3] assert tHandle == handles[3]
# END Test testCoreTree_MakeHandles # END Test testCoreTree_MakeHandles
@@ -474,17 +474,17 @@ def testCoreTree_MakeHandles(mockGUI):
@pytest.mark.core @pytest.mark.core
def testCoreTree_Stats(mockGUI, mockItems): def testCoreTree_Stats(mockGUI, mockItems):
"""Test project stats methods.""" """Test project stats methods."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
for nwItem in mockItems: for nwItem in mockItems:
theTree.append(nwItem) tree.append(nwItem)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
theTree._order.append("stuff") tree._order.append("stuff")
# Count Words # Count Words
novelWords, noteWords = theTree.sumWords() novelWords, noteWords = tree.sumWords()
assert novelWords == 550 assert novelWords == 550
assert noteWords == 400 assert noteWords == 400
@@ -494,33 +494,33 @@ def testCoreTree_Stats(mockGUI, mockItems):
@pytest.mark.core @pytest.mark.core
def testCoreTree_Reorder(caplog, mockGUI, mockItems): def testCoreTree_Reorder(caplog, mockGUI, mockItems):
"""Test changing tree order.""" """Test changing tree order."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
aHandle = [] aHandle = []
for nwItem in mockItems: for nwItem in mockItems:
aHandle.append(nwItem.itemHandle) aHandle.append(nwItem.itemHandle)
theTree.append(nwItem) tree.append(nwItem)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
bHandle = aHandle.copy() bHandle = aHandle.copy()
bHandle[2], bHandle[3] = bHandle[3], bHandle[2] bHandle[2], bHandle[3] = bHandle[3], bHandle[2]
assert aHandle != bHandle assert aHandle != bHandle
assert theTree.handles() == aHandle assert tree.handles() == aHandle
theTree.setOrder(bHandle) tree.setOrder(bHandle)
assert theTree.handles() == bHandle assert tree.handles() == bHandle
caplog.clear() caplog.clear()
theTree.setOrder(bHandle + ["stuff"]) tree.setOrder(bHandle + ["stuff"])
assert theTree.handles() == bHandle assert tree.handles() == bHandle
assert "Handle 'stuff' in new tree order is not in old order" in caplog.text assert "Handle 'stuff' in new tree order is not in old order" in caplog.text
caplog.clear() caplog.clear()
theTree._order.append("stuff") tree._order.append("stuff")
theTree.setOrder(bHandle) tree.setOrder(bHandle)
assert theTree.handles() == bHandle assert tree.handles() == bHandle
assert "Handle 'stuff' in old tree order is not in new order" in caplog.text assert "Handle 'stuff' in old tree order is not in new order" in caplog.text
# END Test testCoreTree_Reorder # END Test testCoreTree_Reorder
@@ -529,40 +529,40 @@ def testCoreTree_Reorder(caplog, mockGUI, mockItems):
@pytest.mark.core @pytest.mark.core
def testCoreTree_ToCFile(monkeypatch, fncPath, mockGUI, mockItems): def testCoreTree_ToCFile(monkeypatch, fncPath, mockGUI, mockItems):
"""Test writing the ToC.txt file.""" """Test writing the ToC.txt file."""
theProject = NWProject() project = NWProject()
theTree = NWTree(theProject) tree = NWTree(project)
for nwItem in mockItems: for nwItem in mockItems:
theTree.append(nwItem) tree.append(nwItem)
theTree.updateItemData(nwItem.itemHandle) tree.updateItemData(nwItem.itemHandle)
assert len(theTree) == len(mockItems) assert len(tree) == len(mockItems)
theTree._order.append("stuff") tree._order.append("stuff")
def mockIsFile(fileName): def mockIsFile(fileName):
"""Return True for items that are files in novelWriter and """Return True for items that are files in novelWriter and
should thus also be files in the project folder structure. should thus also be files in the project folder structure.
""" """
dItem = theTree[fileName.name[:13]] dItem = tree[fileName.name[:13]]
assert dItem is not None assert dItem is not None
return dItem.itemType == nwItemType.FILE return dItem.itemType == nwItemType.FILE
monkeypatch.setattr("pathlib.Path.is_file", mockIsFile) monkeypatch.setattr("pathlib.Path.is_file", mockIsFile)
theProject._storage._runtimePath = fncPath project._storage._runtimePath = fncPath
(fncPath / "content").mkdir() (fncPath / "content").mkdir()
# Block extraction of the path # Block extraction of the path
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.storage.NWStorage.contentPath", lambda *a: None) mp.setattr("novelwriter.core.storage.NWStorage.contentPath", lambda *a: None)
assert theTree.writeToCFile() is False assert tree.writeToCFile() is False
# Block opening the file # Block opening the file
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert theTree.writeToCFile() is False assert tree.writeToCFile() is False
# Allow writing # Allow writing
assert theTree.writeToCFile() is True assert tree.writeToCFile() is True
pathA = str(Path("content") / "c000000000001.nwd") pathA = str(Path("content") / "c000000000001.nwd")
pathB = str(Path("content") / "c000000000002.nwd") pathB = str(Path("content") / "c000000000002.nwd")
+3 -3
View File
@@ -37,7 +37,7 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
# Create a new project # Create a new project
buildTestProject(nwGUI, projPath) buildTestProject(nwGUI, projPath)
theProject = SHARED.project project = SHARED.project
projTree = nwGUI.projView.projTree projTree = nwGUI.projView.projTree
docText = ( docText = (
@@ -55,8 +55,8 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"#### New Section\n\nText\n\n" "#### New Section\n\nText\n\n"
) )
hSplitDoc = theProject.newFile("Split Doc", C.hNovelRoot) hSplitDoc = project.newFile("Split Doc", C.hNovelRoot)
theProject.writeNewFile(hSplitDoc, 1, True, docText) project.writeNewFile(hSplitDoc, 1, True, docText)
projTree.revealNewTreeItem(hSplitDoc, nHandle=C.hNovelRoot, wordCount=True) projTree.revealNewTreeItem(hSplitDoc, nHandle=C.hNovelRoot, wordCount=True)
docText = f"# Split Doc\n\n{docText}" docText = f"# Split Doc\n\n{docText}"
+20 -20
View File
@@ -365,7 +365,7 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
text = "### A Scene\n\n%s" % "\n\n".join(ipsumText) text = "### A Scene\n\n%s" % "\n\n".join(ipsumText)
nwGUI.docEditor.replaceText(text) nwGUI.docEditor.replaceText(text)
theDoc = nwGUI.docEditor.document() doc = nwGUI.docEditor.document()
# Select/Cut/Copy/Paste/Undo/Redo # Select/Cut/Copy/Paste/Undo/Redo
# =============================== # ===============================
@@ -374,17 +374,17 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Select All # Select All
assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL) is True assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL) is True
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.hasSelection() is True assert cursor.hasSelection() is True
assert theCursor.selectedText() == text.replace("\n", "\u2029") assert cursor.selectedText() == text.replace("\n", "\u2029")
theCursor.clearSelection() cursor.clearSelection()
# Select Paragraph # Select Paragraph
nwGUI.docEditor.setCursorPosition(1000) nwGUI.docEditor.setCursorPosition(1000)
assert nwGUI.docEditor.getCursorPosition() == 1000 assert nwGUI.docEditor.getCursorPosition() == 1000
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA) is True assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA) is True
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == ipsumText[1] assert cursor.selectedText() == ipsumText[1]
# Cut Selected Text # Cut Selected Text
nwGUI.docEditor.replaceText(text) nwGUI.docEditor.replaceText(text)
@@ -411,10 +411,10 @@ def testGuiEditor_Actions(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert nwGUI.docEditor.docAction(nwDocAction.COPY) is True assert nwGUI.docEditor.docAction(nwDocAction.COPY) is True
# Paste at End # Paste at End
nwGUI.docEditor.setCursorPosition(theDoc.characterCount()) nwGUI.docEditor.setCursorPosition(doc.characterCount())
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
theCursor.insertBlock() cursor.insertBlock()
theCursor.insertBlock() cursor.insertBlock()
assert nwGUI.docEditor.docAction(nwDocAction.PASTE) is True assert nwGUI.docEditor.docAction(nwDocAction.PASTE) is True
newText = nwGUI.docEditor.getText() newText = nwGUI.docEditor.getText()
@@ -1017,8 +1017,8 @@ def testGuiEditor_BlockFormatting(qtbot, monkeypatch, nwGUI, projPath, ipsumText
# Invalid and Generic # Invalid and Generic
# =================== # ===================
theText = "### A Scene\n\n%s" % ipsumText[0] text = "### A Scene\n\n%s" % ipsumText[0]
nwGUI.docEditor.replaceText(theText) nwGUI.docEditor.replaceText(text)
# Invalid Block # Invalid Block
nwGUI.docEditor.setCursorPosition(0) nwGUI.docEditor.setCursorPosition(0)
@@ -1561,9 +1561,9 @@ def testGuiEditor_WordCounters(qtbot, monkeypatch, nwGUI, projPath, ipsumText, m
SHARED.project.tree[C.hSceneDoc]._wordCount = 0 # type: ignore SHARED.project.tree[C.hSceneDoc]._wordCount = 0 # type: ignore
assert nwGUI.openDocument(C.hSceneDoc) is True assert nwGUI.openDocument(C.hSceneDoc) is True
theText = "\n\n".join(ipsumText) text = "\n\n".join(ipsumText)
cC, wC, pC = countWords(theText) cC, wC, pC = countWords(text)
nwGUI.docEditor.replaceText(theText) nwGUI.docEditor.replaceText(text)
# Check that a busy counter is blocked # Check that a busy counter is blocked
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
@@ -1617,8 +1617,8 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum):
# Select the Word "est" # Select the Word "est"
nwGUI.docEditor.setCursorPosition(630) nwGUI.docEditor.setCursorPosition(630)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor) nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "est" assert cursor.selectedText() == "est"
# Activate search # Activate search
nwGUI.mainMenu.aFind.activate(QAction.Trigger) nwGUI.mainMenu.aFind.activate(QAction.Trigger)
@@ -1747,8 +1747,8 @@ def testGuiEditor_Search(qtbot, monkeypatch, nwGUI, prjLipsum):
nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger) nwGUI.docEditor.docSearch.cancelSearch.activate(QAction.Trigger)
nwGUI.docEditor.setCursorPosition(630) nwGUI.docEditor.setCursorPosition(630)
nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor) nwGUI.docEditor._makeSelection(QTextCursor.WordUnderCursor)
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "est" assert cursor.selectedText() == "est"
# Activate search again # Activate search again
nwGUI.mainMenu.aFind.activate(QAction.Trigger) nwGUI.mainMenu.aFind.activate(QAction.Trigger)
+35 -35
View File
@@ -187,8 +187,8 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
# Select Paragraph/All # Select Paragraph/All
nwGUI.docEditor.setCursorPosition(42) nwGUI.docEditor.setCursorPosition(42)
nwGUI.mainMenu.aSelectPar.activate(QAction.Trigger) nwGUI.mainMenu.aSelectPar.activate(QAction.Trigger)
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == ( assert cursor.selectedText() == (
"Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta " "Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta "
"imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit " "imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit "
"placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. " "placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. "
@@ -200,8 +200,8 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
nwGUI.docEditor.setCursorPosition(42) nwGUI.docEditor.setCursorPosition(42)
nwGUI.mainMenu.aSelectAll.activate(QAction.Trigger) nwGUI.mainMenu.aSelectAll.activate(QAction.Trigger)
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert len(theCursor.selectedText()) == 1895 assert len(cursor.selectedText()) == 1895
# Clear the Text # Clear the Text
nwGUI.docEditor.clear() nwGUI.docEditor.clear()
@@ -295,10 +295,10 @@ def testGuiMenu_EditFormat(qtbot, monkeypatch, nwGUI, prjLipsum):
"Here is some text\non multiple\nlines.\n\n" "Here is some text\non multiple\nlines.\n\n"
"With another paragraph\nhere." "With another paragraph\nhere."
)) ))
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
theCursor.setPosition(74) cursor.setPosition(74)
theCursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 29) cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, 29)
nwGUI.docEditor.setTextCursor(theCursor) nwGUI.docEditor.setTextCursor(cursor)
nwGUI.mainMenu.aFmtRmBreaks.activate(QAction.Trigger) nwGUI.mainMenu.aFmtRmBreaks.activate(QAction.Trigger)
assert nwGUI.docEditor.getText() == ( assert nwGUI.docEditor.getText() == (
"### New Text\n\n" "### New Text\n\n"
@@ -348,21 +348,21 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, prjLipsum):
assert nwGUI.openDocument("4c4f28287af27") assert nwGUI.openDocument("4c4f28287af27")
# Editor Context Menu # Editor Context Menu
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
theCursor.setPosition(112) cursor.setPosition(112)
nwGUI.docEditor.setTextCursor(theCursor) nwGUI.docEditor.setTextCursor(cursor)
theRect = nwGUI.docEditor.cursorRect() rect = nwGUI.docEditor.cursorRect()
nwGUI.docEditor._openContextMenu(theRect.bottomRight()) nwGUI.docEditor._openContextMenu(rect.bottomRight())
qtbot.mouseClick(nwGUI.docEditor, Qt.LeftButton, pos=theRect.topLeft()) qtbot.mouseClick(nwGUI.docEditor, Qt.LeftButton, pos=rect.topLeft())
nwGUI.docEditor._makePosSelection(QTextCursor.WordUnderCursor, theRect.center()) nwGUI.docEditor._makePosSelection(QTextCursor.WordUnderCursor, rect.center())
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == "imperdiet" assert cursor.selectedText() == "imperdiet"
nwGUI.docEditor._makePosSelection(QTextCursor.BlockUnderCursor, theRect.center()) nwGUI.docEditor._makePosSelection(QTextCursor.BlockUnderCursor, rect.center())
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == ( assert cursor.selectedText() == (
"Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta " "Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta "
"imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit " "imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit "
"placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. " "placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. "
@@ -375,21 +375,21 @@ def testGuiMenu_ContextMenus(qtbot, nwGUI, prjLipsum):
# Viewer Context Menu # Viewer Context Menu
assert nwGUI.viewDocument("4c4f28287af27") assert nwGUI.viewDocument("4c4f28287af27")
theCursor = nwGUI.docViewer.textCursor() cursor = nwGUI.docViewer.textCursor()
theCursor.setPosition(112) cursor.setPosition(112)
nwGUI.docViewer.setTextCursor(theCursor) nwGUI.docViewer.setTextCursor(cursor)
theRect = nwGUI.docViewer.cursorRect() rect = nwGUI.docViewer.cursorRect()
nwGUI.docViewer._openContextMenu(theRect.bottomRight()) nwGUI.docViewer._openContextMenu(rect.bottomRight())
qtbot.mouseClick(nwGUI.docViewer, Qt.LeftButton, pos=theRect.topLeft()) qtbot.mouseClick(nwGUI.docViewer, Qt.LeftButton, pos=rect.topLeft())
nwGUI.docViewer._makePosSelection(QTextCursor.WordUnderCursor, theRect.center()) nwGUI.docViewer._makePosSelection(QTextCursor.WordUnderCursor, rect.center())
theCursor = nwGUI.docViewer.textCursor() cursor = nwGUI.docViewer.textCursor()
assert theCursor.selectedText() == "imperdiet" assert cursor.selectedText() == "imperdiet"
nwGUI.docEditor._makePosSelection(QTextCursor.BlockUnderCursor, theRect.center()) nwGUI.docEditor._makePosSelection(QTextCursor.BlockUnderCursor, rect.center())
theCursor = nwGUI.docEditor.textCursor() cursor = nwGUI.docEditor.textCursor()
assert theCursor.selectedText() == ( assert cursor.selectedText() == (
"Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta " "Pellentesque nec erat ut nulla posuere commodo. Curabitur nisi augue, imperdiet et porta "
"imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit " "imperdiet, efficitur id leo. Cras finibus arcu at nibh commodo congue. Proin suscipit "
"placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. " "placerat condimentum. Aenean ante enim, cursus id lorem a, blandit venenatis nibh. "
@@ -629,12 +629,12 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
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 = fncPath / "import.txt" iFile = fncPath / "import.txt"
monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (str(theFile), "")) monkeypatch.setattr(QFileDialog, "getOpenFileName", lambda *a, **k: (str(iFile), ""))
assert not nwGUI.importDocument() assert not nwGUI.importDocument()
# Create the file and try again, but with no target document open # Create the file and try again, but with no target document open
writeFile(theFile, "Foo") writeFile(iFile, "Foo")
assert not nwGUI.importDocument() assert not nwGUI.importDocument()
# Open the document from before, and add some text to it # Open the document from before, and add some text to it
+33 -33
View File
@@ -370,7 +370,7 @@ def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, projPath,
"""Test moving items to Trash.""" """Test moving items to Trash."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True)) monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
theProject = SHARED.project project = SHARED.project
projTree = nwGUI.projView.projTree projTree = nwGUI.projView.projTree
# Create a project # Create a project
@@ -392,7 +392,7 @@ def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, projPath,
caplog.clear() caplog.clear()
assert projTree.moveItemToTrash(C.hTitlePage) is False assert projTree.moveItemToTrash(C.hTitlePage) is False
assert theProject.tree.isTrash(C.hTitlePage) is False assert project.tree.isTrash(C.hTitlePage) is False
assert "Could not delete item" in caplog.text assert "Could not delete item" in caplog.text
projTree._addTrashRoot = funcPointer projTree._addTrashRoot = funcPointer
@@ -401,11 +401,11 @@ def testGuiProjTree_MoveItemToTrash(qtbot, caplog, monkeypatch, nwGUI, projPath,
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No) mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
assert projTree.moveItemToTrash(C.hTitlePage) is False assert projTree.moveItemToTrash(C.hTitlePage) is False
assert theProject.tree.isTrash(C.hTitlePage) is False assert project.tree.isTrash(C.hTitlePage) is False
# Move a document to Trash # Move a document to Trash
assert projTree.moveItemToTrash(C.hTitlePage) is True assert projTree.moveItemToTrash(C.hTitlePage) is True
assert theProject.tree.isTrash(C.hTitlePage) is True assert project.tree.isTrash(C.hTitlePage) is True
# Cannot be moved again # Cannot be moved again
caplog.clear() caplog.clear()
@@ -422,7 +422,7 @@ def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, pro
"""Test permanently deleting items.""" """Test permanently deleting items."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True)) monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
theProject = SHARED.project project = SHARED.project
projTree = nwGUI.projView.projTree projTree = nwGUI.projView.projTree
# Create a project # Create a project
@@ -437,31 +437,31 @@ def testGuiProjTree_PermanentlyDeleteItem(qtbot, caplog, monkeypatch, nwGUI, pro
caplog.clear() caplog.clear()
assert projTree.permDeleteItem(C.hNovelRoot) is False assert projTree.permDeleteItem(C.hNovelRoot) is False
assert "Root folders can only be deleted when they are empty" in caplog.text assert "Root folders can only be deleted when they are empty" in caplog.text
assert C.hNovelRoot in theProject.tree assert C.hNovelRoot in project.tree
# Deleting unused root item is allowed # Deleting unused root item is allowed
caplog.clear() caplog.clear()
assert projTree.permDeleteItem(C.hPlotRoot) is True assert projTree.permDeleteItem(C.hPlotRoot) is True
assert C.hPlotRoot not in theProject.tree assert C.hPlotRoot not in project.tree
# User cancels action # User cancels action
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No) mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
assert projTree.permDeleteItem(C.hTitlePage) is False assert projTree.permDeleteItem(C.hTitlePage) is False
assert C.hTitlePage in theProject.tree assert C.hTitlePage in project.tree
# Deleting file is OK, and if it is open, it should close # Deleting file is OK, and if it is open, it should close
assert nwGUI.openDocument(C.hTitlePage) is True assert nwGUI.openDocument(C.hTitlePage) is True
assert nwGUI.docEditor.docHandle == C.hTitlePage assert nwGUI.docEditor.docHandle == C.hTitlePage
assert projTree.permDeleteItem(C.hTitlePage) is True assert projTree.permDeleteItem(C.hTitlePage) is True
assert C.hTitlePage not in theProject.tree assert C.hTitlePage not in project.tree
assert nwGUI.docEditor.docHandle is None assert nwGUI.docEditor.docHandle is None
# Deleting folder + files recursively is ok # Deleting folder + files recursively is ok
assert projTree.permDeleteItem(C.hChapterDir) is True assert projTree.permDeleteItem(C.hChapterDir) is True
assert C.hChapterDir not in theProject.tree assert C.hChapterDir not in project.tree
assert C.hChapterDoc not in theProject.tree assert C.hChapterDoc not in project.tree
assert C.hSceneDoc not in theProject.tree assert C.hSceneDoc not in project.tree
nwGUI.closeProject() nwGUI.closeProject()
@@ -473,7 +473,7 @@ def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, projPath, mock
"""Test emptying Trash.""" """Test emptying Trash."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True)) monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
theProject = SHARED.project project = SHARED.project
projTree = nwGUI.projView.projTree projTree = nwGUI.projView.projTree
# No project open # No project open
@@ -491,26 +491,26 @@ def testGuiProjTree_EmptyTrash(qtbot, caplog, monkeypatch, nwGUI, projPath, mock
assert projTree.moveItemToTrash(C.hTitlePage) is True assert projTree.moveItemToTrash(C.hTitlePage) is True
assert projTree.moveItemToTrash(C.hChapterDir) is True assert projTree.moveItemToTrash(C.hChapterDir) is True
assert theProject.tree.isTrash(C.hTitlePage) is True assert project.tree.isTrash(C.hTitlePage) is True
assert theProject.tree.isTrash(C.hChapterDir) is True assert project.tree.isTrash(C.hChapterDir) is True
assert theProject.tree.isTrash(C.hChapterDoc) is True assert project.tree.isTrash(C.hChapterDoc) is True
assert theProject.tree.isTrash(C.hSceneDoc) is True assert project.tree.isTrash(C.hSceneDoc) is True
# User cancels # User cancels
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No) mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
assert projTree.emptyTrash() is False assert projTree.emptyTrash() is False
assert C.hTitlePage in theProject.tree assert C.hTitlePage in project.tree
assert C.hChapterDir in theProject.tree assert C.hChapterDir in project.tree
assert C.hChapterDoc in theProject.tree assert C.hChapterDoc in project.tree
assert C.hSceneDoc in theProject.tree assert C.hSceneDoc in project.tree
# Run again to empty all items # Run again to empty all items
assert projTree.emptyTrash() is True assert projTree.emptyTrash() is True
assert C.hTitlePage not in theProject.tree assert C.hTitlePage not in project.tree
assert C.hChapterDir not in theProject.tree assert C.hChapterDir not in project.tree
assert C.hChapterDoc not in theProject.tree assert C.hChapterDoc not in project.tree
assert C.hSceneDoc not in theProject.tree assert C.hSceneDoc not in project.tree
# Running Empty Trash again is cancelled due to empty folder # Running Empty Trash again is cancelled due to empty folder
assert projTree.emptyTrash() is False assert projTree.emptyTrash() is False
@@ -634,7 +634,7 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, projPath, mockRnd,
# Create a project # Create a project
buildTestProject(nwGUI, projPath) buildTestProject(nwGUI, projPath)
theProject = SHARED.project project = SHARED.project
projTree = nwGUI.projView.projTree projTree = nwGUI.projView.projTree
docText = ( docText = (
@@ -652,8 +652,8 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, projPath, mockRnd,
"#### New Section\n\nText\n\n" "#### New Section\n\nText\n\n"
) )
hSplitDoc = theProject.newFile("Split Doc", C.hNovelRoot) hSplitDoc = project.newFile("Split Doc", C.hNovelRoot)
theProject.writeNewFile(hSplitDoc, 1, True, docText) # type: ignore project.writeNewFile(hSplitDoc, 1, True, docText) # type: ignore
projTree.revealNewTreeItem(hSplitDoc, nHandle=C.hNovelRoot, wordCount=True) projTree.revealNewTreeItem(hSplitDoc, nHandle=C.hNovelRoot, wordCount=True)
docText = f"# Split Doc\n\n{docText}" docText = f"# Split Doc\n\n{docText}"
@@ -700,25 +700,25 @@ def testGuiProjTree_SplitDocument(qtbot, monkeypatch, nwGUI, projPath, mockRnd,
mp.setattr("builtins.open", causeOSError) mp.setattr("builtins.open", causeOSError)
assert projTree._splitDocument(hSplitDoc) is True assert projTree._splitDocument(hSplitDoc) is True
for tHandle in fstSet: for tHandle in fstSet:
assert tHandle in theProject.tree assert tHandle in project.tree
assert not (projPath / "content" / f"{tHandle}.nwd").is_file() assert not (projPath / "content" / f"{tHandle}.nwd").is_file()
# Writing succeeds # Writing succeeds
assert projTree._splitDocument(hSplitDoc) is True assert projTree._splitDocument(hSplitDoc) is True
for tHandle in sndSet: for tHandle in sndSet:
assert tHandle in theProject.tree assert tHandle in project.tree
assert (projPath / "content" / f"{tHandle}.nwd").is_file() assert (projPath / "content" / f"{tHandle}.nwd").is_file()
# Add to a folder and move source to trash # Add to a folder and move source to trash
splitData["intoFolder"] = True splitData["intoFolder"] = True
splitData["moveToTrash"] = True splitData["moveToTrash"] = True
assert projTree._splitDocument(hSplitDoc) is True assert projTree._splitDocument(hSplitDoc) is True
assert "0000000000029" in theProject.tree # The folder assert "0000000000029" in project.tree # The folder
for tHandle in trdSet: for tHandle in trdSet:
assert tHandle in theProject.tree assert tHandle in project.tree
assert (projPath / "content" / f"{tHandle}.nwd").is_file() assert (projPath / "content" / f"{tHandle}.nwd").is_file()
assert theProject.tree.isTrash(hSplitDoc) is True # type: ignore assert project.tree.isTrash(hSplitDoc) is True # type: ignore
# Cancelled by user # Cancelled by user
with monkeypatch.context() as mp: with monkeypatch.context() as mp: