From db8140418e06f1a3908eb44ba82afa3beadc900b Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Sat, 3 Jun 2023 18:05:04 +0200
Subject: [PATCH] Fix typing and docstrings in Project data and XML classes
---
novelwriter/common.py | 10 +-
novelwriter/core/projectdata.py | 155 ++++++++++++-----------
novelwriter/core/projectxml.py | 216 ++++++++++++++++----------------
3 files changed, 192 insertions(+), 189 deletions(-)
diff --git a/novelwriter/common.py b/novelwriter/common.py
index 3ccdd751..386681e4 100644
--- a/novelwriter/common.py
+++ b/novelwriter/common.py
@@ -1,7 +1,6 @@
"""
novelWriter – Common Functions
==============================
-Various common functions
File History:
Created: 2019-05-12 [0.1]
@@ -113,9 +112,8 @@ def checkHandle(value, default, allowNone=False):
return default
-def checkUuid(value, default):
- """Try to process a value as an uuid, or return a default.
- """
+def checkUuid(value: Any, default: str) -> str:
+ """Try to process a value as an uuid, or return a default."""
try:
return str(uuid.UUID(value))
except Exception:
@@ -236,7 +234,7 @@ def formatInt(value):
return str(value)
-def formatTimeStamp(value, fileSafe=False):
+def formatTimeStamp(value: float, fileSafe: bool = False) -> str:
"""Take a number (on the format returned by time.time()) and convert
it to a timestamp string.
"""
@@ -246,7 +244,7 @@ def formatTimeStamp(value, fileSafe=False):
return datetime.fromtimestamp(value).strftime(nwConst.FMT_TSTAMP)
-def formatTime(t):
+def formatTime(t: int) -> str:
"""Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format
if a full day or longer.
"""
diff --git a/novelwriter/core/projectdata.py b/novelwriter/core/projectdata.py
index ad376cd1..50c48086 100644
--- a/novelwriter/core/projectdata.py
+++ b/novelwriter/core/projectdata.py
@@ -1,7 +1,6 @@
"""
novelWriter – Project Data Class
================================
-Data class for novelWriter projects
File History:
Created: 2022-10-30 [2.0rc2]
@@ -27,6 +26,8 @@ from __future__ import annotations
import uuid
import logging
+from typing import Any
+
from novelwriter.common import (
checkBool, checkInt, checkStringNone, checkUuid, isHandle, simplified
)
@@ -36,6 +37,11 @@ logger = logging.getLogger(__name__)
class NWProjectData:
+ """Core: Project Data Class
+
+ The class holds all project data from the main XML file, aside from
+ the list of project items.
+ """
def __init__(self, theProject):
@@ -84,75 +90,99 @@ class NWProjectData:
##
@property
- def uuid(self):
+ def uuid(self) -> str:
+ """Return the project ID."""
return self._uuid
@property
- def name(self):
+ def name(self) -> str:
+ """Return the project name."""
return self._name
@property
- def title(self):
+ def title(self) -> str:
+ """Return the project title."""
return self._title
@property
- def author(self):
+ def author(self) -> str:
+ """Return the project author."""
return self._author
@property
- def saveCount(self):
+ def saveCount(self) -> int:
+ """Return the count of project saves."""
return self._saveCount
@property
- def autoCount(self):
+ def autoCount(self) -> int:
+ """Return the count of project auto-saves."""
return self._autoCount
@property
- def editTime(self):
+ def editTime(self) -> int:
+ """Return the number of seconds the project has been edited."""
return self._editTime
@property
- def doBackup(self):
+ def doBackup(self) -> bool:
+ """Return the backup setting."""
return self._doBackup
@property
- def language(self):
+ def language(self) -> str | None:
+ """Return the project language setting."""
return self._language
@property
- def spellCheck(self):
+ def spellCheck(self) -> bool:
+ """Return the spell check enabled setting."""
return self._spellCheck
@property
- def spellLang(self):
+ def spellLang(self) -> str | None:
+ """Return the spell check language."""
return self._spellLang
@property
- def initCounts(self):
+ def initCounts(self) -> tuple[int, int]:
+ """Return the initial count of words for novel and note
+ documents.
+ """
return tuple(self._initCounts)
@property
- def currCounts(self):
+ def currCounts(self) -> tuple[int, int]:
+ """Return the current count of words for novel and note
+ documents.
+ """
return tuple(self._currCounts)
@property
- def lastHandle(self):
+ def lastHandle(self) -> dict[str, str | None]:
+ """Return the dictionary of last used handles for various
+ components of the GUI.
+ """
return self._lastHandle
@property
- def autoReplace(self):
+ def autoReplace(self) -> dict[str, str]:
+ """Return the autoreplace dictionary."""
return self._autoReplace
@property
def titleFormat(self):
+ """Delete"""
return self._titleFormat
@property
- def itemStatus(self):
+ def itemStatus(self) -> NWStatus:
+ """Return the status settings object."""
return self._status
@property
- def itemImport(self):
+ def itemImport(self) -> NWStatus:
+ """Return the importance settings object."""
return self._import
##
@@ -160,15 +190,13 @@ class NWProjectData:
##
def incSaveCount(self):
- """Increment the save count by one.
- """
+ """Increment the save count by one."""
self._saveCount += 1
self.theProject.setProjectChanged(True)
return
def incAutoCount(self):
- """Increment the auto save count by one.
- """
+ """Increment the auto save count by one."""
self._autoCount += 1
self.theProject.setProjectChanged(True)
return
@@ -177,23 +205,20 @@ class NWProjectData:
# Getters
##
- def getLastHandle(self, component):
- """Retrieve the last used handle for a given component.
- """
+ def getLastHandle(self, component: str) -> str | None:
+ """Retrieve the last used handle for a given component."""
return self._lastHandle.get(component, None)
def getTitleFormat(self, kind):
- """Retrieve the title format string for a given kind of header.
- """
+ """Retrieve the title format string for a given kind of header."""
return self._titleFormat.get(kind, "%title%")
##
# Setters
##
- def setUuid(self, value):
- """Set the project id.
- """
+ def setUuid(self, value: Any):
+ """Set the project id."""
value = checkUuid(value, "")
if not value:
self._uuid = str(uuid.uuid4())
@@ -202,84 +227,74 @@ class NWProjectData:
self.theProject.setProjectChanged(True)
return
- def setName(self, value):
- """Set a new project name.
- """
+ def setName(self, value: str | None):
+ """Set a new project name."""
if value != self._name:
self._name = simplified(str(value or ""))
self.theProject.setProjectChanged(True)
return
- def setTitle(self, value):
- """Set a new novel title.
- """
+ def setTitle(self, value: str | None):
+ """Set a new novel title."""
if value != self._title:
self._title = simplified(str(value or ""))
self.theProject.setProjectChanged(True)
return
- def setAuthor(self, value):
- """Set the author value.
- """
+ def setAuthor(self, value: str | None):
+ """Set the author value."""
if value != self._title:
self._author = simplified(str(value or ""))
self.theProject.setProjectChanged(True)
return
- def setSaveCount(self, value):
- """Set the save count from last session.
- """
+ def setSaveCount(self, value: Any):
+ """Set the save count from last session."""
self._saveCount = checkInt(value, 0)
self.theProject.setProjectChanged(True)
return
- def setAutoCount(self, value):
- """Set the auto save count from last session.
- """
+ def setAutoCount(self, value: Any):
+ """Set the auto save count from last session."""
self._autoCount = checkInt(value, 0)
self.theProject.setProjectChanged(True)
return
- def setEditTime(self, value):
- """Set tyje edit time from last session.
- """
+ def setEditTime(self, value: Any):
+ """Set tyje edit time from last session."""
self._editTime = checkInt(value, 0)
self.theProject.setProjectChanged(True)
return
- def setDoBackup(self, value):
- """Set the do write backup flag.
- """
+ def setDoBackup(self, value: Any):
+ """Set the do write backup flag."""
if value != self._doBackup:
self._doBackup = checkBool(value, False)
self.theProject.setProjectChanged(True)
return
- def setLanguage(self, value):
- """Set the project language.
- """
+ def setLanguage(self, value: str | None):
+ """Set the project language."""
if value != self._language:
self._language = checkStringNone(value, None)
self.theProject.setProjectChanged(True)
return
- def setSpellCheck(self, value):
- """Set the spell check flag.
- """
+ def setSpellCheck(self, value: Any):
+ """Set the spell check flag."""
if value != self._spellCheck:
self._spellCheck = checkBool(value, False)
self.theProject.setProjectChanged(True)
return
- def setSpellLang(self, value):
- """Set the spell check language.
- """
+ def setSpellLang(self, value: str | None):
+ """Set the spell check language."""
if value != self._spellLang:
self._spellLang = checkStringNone(value, None)
self.theProject.setProjectChanged(True)
return
- def setLastHandle(self, value, component=None):
+ def setLastHandle(self, value: dict, component: str | None = None):
"""Set a last used handle into the handle registry. If component
is None, the value is assumed to be the whole dictionary of
values.
@@ -294,9 +309,8 @@ class NWProjectData:
self.theProject.setProjectChanged(True)
return
- def setInitCounts(self, novel=None, notes=None):
- """Set the worc count totals for novel and note files.
- """
+ def setInitCounts(self, novel: Any = None, notes: Any = None):
+ """Set the word count totals for novel and note files."""
if novel is not None:
self._initCounts[0] = checkInt(novel, 0)
self._currCounts[0] = checkInt(novel, 0)
@@ -305,18 +319,16 @@ class NWProjectData:
self._currCounts[1] = checkInt(notes, 0)
return
- def setCurrCounts(self, novel=None, notes=None):
- """Set the worc count totals for novel and note files.
- """
+ def setCurrCounts(self, novel: Any = None, notes: Any = None):
+ """Set the word count totals for novel and note files."""
if novel is not None:
self._currCounts[0] = checkInt(novel, 0)
if notes is not None:
self._currCounts[1] = checkInt(notes, 0)
return
- def setAutoReplace(self, value):
- """Set the auto-replace dictionary.
- """
+ def setAutoReplace(self, value: dict):
+ """Set the auto-replace dictionary."""
if isinstance(value, dict):
self._autoReplace = {}
for key, entry in value.items():
@@ -326,8 +338,7 @@ class NWProjectData:
return
def setTitleFormat(self, value):
- """Set the title formats.
- """
+ """Set the title formats."""
if isinstance(value, dict):
for key, entry in value.items():
if key in self._titleFormat and isinstance(entry, str):
diff --git a/novelwriter/core/projectxml.py b/novelwriter/core/projectxml.py
index b39356a2..0726d7da 100644
--- a/novelwriter/core/projectxml.py
+++ b/novelwriter/core/projectxml.py
@@ -1,7 +1,6 @@
"""
novelWriter – Project XML Read/Write
====================================
-Classes for reading and writing the project XML file
File History:
Created: 2022-09-28 [2.0rc2] XMLReadState
@@ -24,6 +23,7 @@ General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+from __future__ import annotations
import logging
import xml.etree.ElementTree as ET
@@ -31,6 +31,7 @@ import xml.etree.ElementTree as ET
from enum import Enum
from time import time
from pathlib import Path
+from typing import TYPE_CHECKING
from novelwriter import __version__, __hexversion__
from novelwriter.common import (
@@ -39,6 +40,10 @@ from novelwriter.common import (
)
from novelwriter.constants import nwFiles
+if TYPE_CHECKING:
+ from novelwriter.core.status import NWStatus
+ from novelwriter.core.projectdata import NWProjectData
+
logger = logging.getLogger(__name__)
FILE_VERSION = "1.5" # The current project file format version
@@ -55,6 +60,7 @@ NUM_VERSION = {
class XMLReadState(Enum):
+ """The state of an XML read process."""
NO_ACTION = 0
NO_ERROR = 1
@@ -69,8 +75,10 @@ class XMLReadState(Enum):
class ProjectXMLReader:
- """The main project XML file reader class. All data is read into a
- NWProjectData instance, which must be provided.
+ """Core: Project XML Reader
+
+ All data is read into a NWProjectData instance, which must be
+ provided.
File Format Version Change History
==================================
@@ -100,16 +108,13 @@ class ProjectXMLReader:
"""
def __init__(self, path):
-
self._path = Path(path)
self._state = XMLReadState.NO_ACTION
-
self._root = ""
self._version = 0x0
self._appVersion = ""
self._hexVersion = 0x0
self._timeStamp = ""
-
return
##
@@ -117,55 +122,46 @@ class ProjectXMLReader:
##
@property
- def state(self):
- """The state of the parsing as an XMLReadState enum value.
- """
+ def state(self) -> XMLReadState:
+ """Return the parsing state."""
return self._state
@property
- def xmlRoot(self):
- """The root tag name of the XNL file,
- """
+ def xmlRoot(self) -> str:
+ """Return the root tag name of the XNL file."""
return self._root
@property
- def xmlVersion(self):
- """The project XML version number.
- """
+ def xmlVersion(self) -> int:
+ """Return the project XML version number."""
return self._version
@property
- def appVersion(self):
- """The novelWriter version number who wrote the file.
- """
+ def appVersion(self) -> str:
+ """Return the version number who wrote the file."""
return self._appVersion
@property
- def hexVersion(self):
- """The novelWriter version number who wrote the file as hex.
- """
+ def hexVersion(self) -> int:
+ """Return the version number who wrote the file as hex."""
return self._hexVersion
@property
- def timeStamp(self):
- """The date and time when the file was written.
- """
+ def timeStamp(self) -> str:
+ """Return the date and time when the file was written."""
return self._timeStamp
##
# Methods
##
- def read(self, projData, projContent):
- """Read and parse the project XML file.
- """
+ def read(self, data: NWProjectData, content: list) -> bool:
+ """Read and parse the project XML file."""
tStart = time()
logger.debug("Reading project XML")
-
try:
xml = ET.parse(str(self._path))
self._state = XMLReadState.NO_ERROR
-
except Exception as exc:
# Trying to open backup file instead
logger.error("Failed to parse project XML", exc_info=exc)
@@ -206,14 +202,14 @@ class ProjectXMLReader:
for xSection in xRoot:
if xSection.tag == "project":
- self._parseProjectMeta(xSection, projData)
+ self._parseProjectMeta(xSection, data)
elif xSection.tag == "settings":
- self._parseProjectSettings(xSection, projData)
+ self._parseProjectSettings(xSection, data)
elif xSection.tag == "content":
if self._version >= 0x0104:
- self._parseProjectContent(xSection, projData, projContent)
+ self._parseProjectContent(xSection, data, content)
else:
- self._parseProjectContentLegacy(xSection, projData, projContent)
+ self._parseProjectContentLegacy(xSection, data, content)
else:
logger.warning("Ignored in XML", xSection.tag)
@@ -230,23 +226,22 @@ class ProjectXMLReader:
# Internal Functions
##
- def _parseProjectMeta(self, xSection, projData):
- """Parse the project section of the XML file.
- """
+ def _parseProjectMeta(self, xSection: ET.Element, data: NWProjectData):
+ """Parse the project section of the XML file."""
logger.debug("Parsing section")
- projData.setUuid(xSection.attrib.get("id", None)) # Added in 1.5
- projData.setSaveCount(xSection.attrib.get("saveCount", 0)) # Moved in 1.5
- projData.setAutoCount(xSection.attrib.get("autoCount", 0)) # Moved in 1.5
- projData.setEditTime(xSection.attrib.get("editTime", 0)) # Moved in 1.5
+ data.setUuid(xSection.attrib.get("id", None)) # Added in 1.5
+ data.setSaveCount(xSection.attrib.get("saveCount", 0)) # Moved in 1.5
+ data.setAutoCount(xSection.attrib.get("autoCount", 0)) # Moved in 1.5
+ data.setEditTime(xSection.attrib.get("editTime", 0)) # Moved in 1.5
for xItem in xSection:
if xItem.tag == "name":
- projData.setName(xItem.text)
+ data.setName(xItem.text)
elif xItem.tag == "title":
- projData.setTitle(xItem.text)
+ data.setTitle(xItem.text)
elif xItem.tag == "author":
- projData.setAuthor(xItem.text)
+ data.setAuthor(xItem.text)
else:
logger.warning("Ignored in XML", xItem.tag)
@@ -254,43 +249,42 @@ class ProjectXMLReader:
if self._version < HEX_VERSION:
for xItem in xSection:
if xItem.tag == "saveCount": # Moved to attribute in 1.5
- projData.setSaveCount(xItem.text)
+ data.setSaveCount(xItem.text)
elif xItem.tag == "autoCount": # Moved to attribute in 1.5
- projData.setAutoCount(xItem.text)
+ data.setAutoCount(xItem.text)
elif xItem.tag == "editTime": # Moved to attribute in 1.5
- projData.setEditTime(xItem.text)
+ data.setEditTime(xItem.text)
return
- def _parseProjectSettings(self, xSection, projData):
- """Parse the settings section of the XML file.
- """
+ def _parseProjectSettings(self, xSection: ET.Element, data: NWProjectData):
+ """Parse the settings section of the XML file."""
logger.debug("Parsing section")
for xItem in xSection:
if xItem.tag == "doBackup":
- projData.setDoBackup(xItem.text)
+ data.setDoBackup(xItem.text)
elif xItem.tag == "language":
- projData.setLanguage(xItem.text)
+ data.setLanguage(xItem.text)
elif xItem.tag == "spellChecking":
- projData.setSpellLang(xItem.text)
- projData.setSpellCheck(xItem.attrib.get("auto", False))
+ data.setSpellLang(xItem.text)
+ data.setSpellCheck(xItem.attrib.get("auto", False))
elif xItem.tag == "status":
- self._parseStatusImport(xItem, projData.itemStatus)
+ self._parseStatusImport(xItem, data.itemStatus)
elif xItem.tag == "importance":
- self._parseStatusImport(xItem, projData.itemImport)
+ self._parseStatusImport(xItem, data.itemImport)
elif xItem.tag == "lastHandle":
- projData.setLastHandle(self._parseDictKeyText(xItem))
+ data.setLastHandle(self._parseDictKeyText(xItem))
elif xItem.tag == "autoReplace":
if self._version >= 0x0102:
- projData.setAutoReplace(self._parseDictKeyText(xItem))
+ data.setAutoReplace(self._parseDictKeyText(xItem))
else: # Pre 1.2 format
- projData.setAutoReplace(self._parseDictTagText(xItem))
+ data.setAutoReplace(self._parseDictTagText(xItem))
elif xItem.tag == "titleFormat":
if self._version >= 0x0105:
- projData.setTitleFormat(self._parseDictKeyText(xItem))
+ data.setTitleFormat(self._parseDictKeyText(xItem))
else: # Pre 1.4 format
- projData.setTitleFormat(self._parseDictTagText(xItem))
+ data.setTitleFormat(self._parseDictTagText(xItem))
else:
logger.warning("Ignored in XML", xItem.tag)
@@ -298,23 +292,22 @@ class ProjectXMLReader:
if self._version < HEX_VERSION:
for xItem in xSection:
if xItem.tag == "spellCheck": # Changed to spellChecking in 1.5
- projData.setSpellCheck(xItem.text)
+ data.setSpellCheck(xItem.text)
elif xItem.tag == "spellLang": # Changed to spellChecking in 1.5
- projData.setSpellLang(xItem.text)
+ data.setSpellLang(xItem.text)
elif xItem.tag == "novelWordCount": # Moved to content attribute in 1.5
- projData.setInitCounts(novel=xItem.text)
+ data.setInitCounts(novel=xItem.text)
elif xItem.tag == "notesWordCount": # Moved to content attribute in 1.5
- projData.setInitCounts(notes=xItem.text)
+ data.setInitCounts(notes=xItem.text)
return
- def _parseProjectContent(self, xSection, projData, projContent):
- """Parse the content section of the XML file.
- """
+ def _parseProjectContent(self, xSection: ET.Element, data: NWProjectData, content: list):
+ """Parse the content section of the XML file."""
logger.debug("Parsing section")
- projData.setInitCounts(novel=xSection.attrib.get("novelWords", None)) # Moved in 1.5
- projData.setInitCounts(notes=xSection.attrib.get("notesWords", None)) # Moved in 1.5
+ data.setInitCounts(novel=xSection.attrib.get("novelWords", None)) # Moved in 1.5
+ data.setInitCounts(notes=xSection.attrib.get("notesWords", None)) # Moved in 1.5
for xItem in xSection:
if xItem.tag != "item":
@@ -355,7 +348,7 @@ class ProjectXMLReader:
if xVal.tag == "name" and "exported" in xVal.attrib:
name["active"] = checkBool(xVal.attrib.get("exported"), False)
- projContent.append({
+ content.append({
"name": itemName,
"itemAttr": item,
"metaAttr": meta,
@@ -364,14 +357,13 @@ class ProjectXMLReader:
return
- def _parseProjectContentLegacy(self, xSection, projData, projContent):
- """Parse the content section of the XML file for older versions.
- """
+ def _parseProjectContentLegacy(self, xSection: ET.Element, data: NWProjectData, content: list):
+ """Parse the content section of the XML file for older versions."""
logger.debug("Parsing section (legacy format)")
# Create maps to look up name -> key for status and importance
- statusMap = {entry.get("name"): key for key, entry in projData.itemStatus.items()}
- importMap = {entry.get("name"): key for key, entry in projData.itemImport.items()}
+ statusMap = {entry.get("name"): key for key, entry in data.itemStatus.items()}
+ importMap = {entry.get("name"): key for key, entry in data.itemImport.items()}
for xItem in xSection:
if xItem.tag != "item":
@@ -432,7 +424,7 @@ class ProjectXMLReader:
if item.get("type", "") == "TRASH":
item["type"] = "ROOT"
- projContent.append({
+ content.append({
"name": itemName,
"itemAttr": item,
"metaAttr": meta,
@@ -441,9 +433,8 @@ class ProjectXMLReader:
return
- def _parseStatusImport(self, xItem, sObject):
- """Parse a status or importance entry.
- """
+ def _parseStatusImport(self, xItem: ET.Element, sObject: NWStatus):
+ """Parse a status or importance entry."""
for xEntry in xItem:
if xEntry.tag == "entry":
key = xEntry.attrib.get("key", None)
@@ -454,7 +445,7 @@ class ProjectXMLReader:
sObject.write(key, xEntry.text, (red, green, blue), count)
return
- def _parseDictKeyText(self, xItem):
+ def _parseDictKeyText(self, xItem: ET.Element) -> dict:
"""Parse a dictionary stored with key as an attribute and the
value as the text porperty.
"""
@@ -474,12 +465,15 @@ class ProjectXMLReader:
class ProjectXMLWriter:
+ """Core: Project XML Writer
+
+ The project writer class will only write a file according to the
+ very latest spec.
+ """
def __init__(self, path):
-
self._path = Path(path)
self._error = None
-
return
##
@@ -487,16 +481,16 @@ class ProjectXMLWriter:
##
@property
- def error(self):
+ def error(self) -> Exception | None:
+ """Return the error status."""
return self._error
##
# Methods
##
- def write(self, projData, projContent, saveTime, editTime):
- """Write the project data and content to the XML files.
- """
+ def write(self, data: NWProjectData, content: list, saveTime: float, editTime: int) -> bool:
+ """Write the project data and content to the XML files."""
tStart = time()
logger.debug("Writing project XML")
@@ -509,46 +503,46 @@ class ProjectXMLWriter:
# Save Project Meta
projAttr = {
- "id": projData.uuid,
- "saveCount": str(projData.saveCount),
- "autoCount": str(projData.autoCount),
+ "id": data.uuid,
+ "saveCount": str(data.saveCount),
+ "autoCount": str(data.autoCount),
"editTime": str(editTime),
}
xProject = ET.SubElement(xRoot, "project", attrib=projAttr)
- self._packSingleValue(xProject, "name", projData.name)
- self._packSingleValue(xProject, "title", projData.title)
- self._packSingleValue(xProject, "author", projData.author)
+ self._packSingleValue(xProject, "name", data.name)
+ self._packSingleValue(xProject, "title", data.title)
+ self._packSingleValue(xProject, "author", data.author)
# Save Project Settings
xSettings = ET.SubElement(xRoot, "settings")
- self._packSingleValue(xSettings, "doBackup", yesNo(projData.doBackup))
- self._packSingleValue(xSettings, "language", projData.language)
- self._packSingleValue(xSettings, "spellChecking", projData.spellLang, attrib={
- "auto": yesNo(projData.spellCheck)
+ self._packSingleValue(xSettings, "doBackup", yesNo(data.doBackup))
+ self._packSingleValue(xSettings, "language", data.language)
+ self._packSingleValue(xSettings, "spellChecking", data.spellLang, attrib={
+ "auto": yesNo(data.spellCheck)
})
- self._packDictKeyValue(xSettings, "lastHandle", projData.lastHandle)
- self._packDictKeyValue(xSettings, "autoReplace", projData.autoReplace)
- self._packDictKeyValue(xSettings, "titleFormat", projData.titleFormat)
+ self._packDictKeyValue(xSettings, "lastHandle", data.lastHandle)
+ self._packDictKeyValue(xSettings, "autoReplace", data.autoReplace)
+ self._packDictKeyValue(xSettings, "titleFormat", data.titleFormat)
# Save Status/Importance
xStatus = ET.SubElement(xSettings, "status")
- for label, attrib in projData.itemStatus.pack():
+ for label, attrib in data.itemStatus.pack():
self._packSingleValue(xStatus, "entry", label, attrib=attrib)
xImport = ET.SubElement(xSettings, "importance")
- for label, attrib in projData.itemImport.pack():
+ for label, attrib in data.itemImport.pack():
self._packSingleValue(xImport, "entry", label, attrib=attrib)
# Save Tree Content
contAttr = {
- "items": str(len(projContent)),
- "novelWords": str(projData.currCounts[0]),
- "notesWords": str(projData.currCounts[1]),
+ "items": str(len(content)),
+ "novelWords": str(data.currCounts[0]),
+ "notesWords": str(data.currCounts[1]),
}
xContent = ET.SubElement(xRoot, "content", attrib=contAttr)
- for item in projContent:
+ for item in content:
xItem = ET.SubElement(xContent, "item", attrib=item.get("itemAttr", {}))
ET.SubElement(xItem, "meta", attrib=item.get("metaAttr", {}))
xName = ET.SubElement(xItem, "name", attrib=item.get("nameAttr", {}))
@@ -584,16 +578,16 @@ class ProjectXMLWriter:
# Internal Functions
##
- def _packSingleValue(self, xParent, name, value, attrib=None):
- """Pack a single value into an XML element.
- """
+ def _packSingleValue(
+ self, xParent: ET.Element, name: str, value: str | None, attrib: dict | None = None
+ ):
+ """Pack a single value into an XML element."""
xItem = ET.SubElement(xParent, name, attrib=attrib or {})
xItem.text = str(value) or ""
return
- def _packDictKeyValue(self, xParent, name, data):
- """Pack the entries of a dictionary into an XML element.
- """
+ def _packDictKeyValue(self, xParent: ET.Element, name: str, data: dict):
+ """Pack the entries of a dictionary into an XML element."""
xItem = ET.SubElement(xParent, name)
for key, value in data.items():
if len(key) > 0: