Пример #1
0
def testCoreProject_NewFile(fncDir, outDir, refDir, mockGUI):
    """Check that new files can be added to the project.
    """
    projFile = os.path.join(fncDir, "nwProject.nwx")
    testFile = os.path.join(outDir, "coreProject_NewFile_nwProject.nwx")
    compFile = os.path.join(refDir, "coreProject_NewFile_nwProject.nwx")

    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)

    assert theProject.newProject({"projPath": fncDir}) is True
    assert theProject.setProjectPath(fncDir) is True
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True
    assert theProject.openProject(projFile) is True

    assert isinstance(
        theProject.newFile("Hello", nwItemClass.NOVEL, "31489056e0916"), str)
    assert isinstance(
        theProject.newFile("Jane", nwItemClass.CHARACTER, "71ee45a3c0db9"),
        str)
    assert theProject.projChanged
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True

    copyfile(projFile, testFile)
    assert cmpFiles(testFile, compFile, [2, 6, 7, 8])
    assert theProject.projChanged is False
Пример #2
0
def testCoreProject_AccessItems(nwMinimal, mockGUI):
    """Test helper functions for the project folder.
    """
    theProject = NWProject(mockGUI)
    theProject.openProject(nwMinimal)

    # Move Novel ROOT to after its files
    oldOrder = [
        "a508bb932959c",  # ROOT: Novel
        "a35baf2e93843",  # FILE: Title Page
        "a6d311a93600a",  # FOLDER: New Chapter
        "f5ab3e30151e1",  # FILE: New Chapter
        "8c659a11cd429",  # FILE: New Scene
        "7695ce551d265",  # ROOT: Plot
        "afb3043c7b2b3",  # ROOT: Characters
        "9d5247ab588e0",  # ROOT: World
    ]
    newOrder = [
        "a35baf2e93843",  # FILE: Title Page
        "f5ab3e30151e1",  # FILE: New Chapter
        "8c659a11cd429",  # FILE: New Scene
        "a6d311a93600a",  # FOLDER: New Chapter
        "a508bb932959c",  # ROOT: Novel
        "7695ce551d265",  # ROOT: Plot
        "afb3043c7b2b3",  # ROOT: Characters
        "9d5247ab588e0",  # ROOT: World
    ]
    assert theProject.projTree.handles() == oldOrder
    assert theProject.setTreeOrder(newOrder)
    assert theProject.projTree.handles() == newOrder

    # Add a non-existing item
    theProject.projTree._treeOrder.append("01234567789abc")

    # Add an item with a non-existent parent
    nHandle = theProject.newFile("Test File", nwItemClass.NOVEL,
                                 "a6d311a93600a")
    theProject.projTree[nHandle].setParent("cba9876543210")
    assert theProject.projTree[nHandle].itemParent == "cba9876543210"

    retOrder = []
    for tItem in theProject.getProjectItems():
        retOrder.append(tItem.itemHandle)

    assert retOrder == [
        "a508bb932959c",  # ROOT: Novel
        "7695ce551d265",  # ROOT: Plot
        "afb3043c7b2b3",  # ROOT: Characters
        "9d5247ab588e0",  # ROOT: World
        nHandle,  # FILE: Test File
        "a35baf2e93843",  # FILE: Title Page
        "a6d311a93600a",  # FOLDER: New Chapter
        "f5ab3e30151e1",  # FILE: New Chapter
        "8c659a11cd429",  # FILE: New Scene
    ]
    assert theProject.projTree[nHandle].itemParent is None
Пример #3
0
def testCoreIndex_ExtractData(nwMinimal, mockGUI):
    """Check the index data extraction functions.
    """
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal) is True

    theIndex = NWIndex(theProject)
    nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
    cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER,
                                 "afb3043c7b2b3")

    assert theIndex.getNovelData("", "") is None
    assert theIndex.getNovelData("a508bb932959c", "") is None

    assert theIndex.scanText(cHandle, ("# Jane Smith\n" "@tag: Jane\n"))
    assert theIndex.scanText(nHandle, ("# Hello World!\n"
                                       "@pov: Jane\n"
                                       "@char: Jane\n\n"
                                       "% this is a comment\n\n"
                                       "This is a story about Jane Smith.\n\n"
                                       "Well, not really.\n"))

    # The novel structure should contain the pointer to the novel file header
    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure():
        theKeys.append(aKey)

    assert theKeys == ["%s:T000001" % nHandle]

    # Check that excluded files can be skipped
    theProject.projTree[nHandle].setExported(False)

    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure(skipExcluded=False):
        theKeys.append(aKey)

    assert theKeys == ["%s:T000001" % nHandle]

    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure(skipExcluded=True):
        theKeys.append(aKey)

    assert theKeys == []

    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure():
        theKeys.append(aKey)

    assert theKeys == []

    # The novel file should have the correct counts
    cC, wC, pC = theIndex.getCounts(nHandle)
    assert cC == 62  # Characters in text and title only
    assert wC == 12  # Words in text and title only
    assert pC == 2  # Paragraphs in text only

    # getReferences
    # =============

    # Look up an ivalid handle
    theRefs = theIndex.getReferences("Not a handle")
    assert theRefs["@pov"] == []
    assert theRefs["@char"] == []

    # The novel file should now refer to Jane as @pov and @char
    theRefs = theIndex.getReferences(nHandle)
    assert theRefs["@pov"] == ["Jane"]
    assert theRefs["@char"] == ["Jane"]

    # getBackReferenceList
    # ====================

    # None handle should return an empty dict
    assert theIndex.getBackReferenceList(None) == {}

    # The character file should have a record of the reference from the novel file
    theRefs = theIndex.getBackReferenceList(cHandle)
    assert theRefs == {nHandle: "T000001"}

    # getTagSource
    # ============

    assert theIndex.getTagSource("Jane") == (cHandle, 2, "T000001")
    assert theIndex.getTagSource("John") == (None, 0, "T000000")

    # getCounts
    # =========
    # For whole text and sections

    # Get section counts for a novel file
    assert theIndex.scanText(
        nHandle, ("# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really.\n\n"
                  "# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really. She's still awesome though.\n"))
    # Whole document
    cC, wC, pC = theIndex.getCounts(nHandle)
    assert cC == 152
    assert wC == 28
    assert pC == 4

    # First part
    cC, wC, pC = theIndex.getCounts(nHandle, "T000001")
    assert cC == 62
    assert wC == 12
    assert pC == 2

    # Second part
    cC, wC, pC = theIndex.getCounts(nHandle, "T000011")
    assert cC == 90
    assert wC == 16
    assert pC == 2

    # Get section counts for a note file
    assert theIndex.scanText(
        cHandle, ("# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really.\n\n"
                  "# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really. She's still awesome though.\n"))
    # Whole document
    cC, wC, pC = theIndex.getCounts(cHandle)
    assert cC == 152
    assert wC == 28
    assert pC == 4

    # First part
    cC, wC, pC = theIndex.getCounts(cHandle, "T000001")
    assert cC == 62
    assert wC == 12
    assert pC == 2

    # Second part
    cC, wC, pC = theIndex.getCounts(cHandle, "T000011")
    assert cC == 90
    assert wC == 16
    assert pC == 2

    # Novel Stats
    # ===========

    hHandle = theProject.newFile("Chapter", nwItemClass.NOVEL, "a508bb932959c")
    sHandle = theProject.newFile("Scene One", nwItemClass.NOVEL,
                                 "a508bb932959c")
    tHandle = theProject.newFile("Scene Two", nwItemClass.NOVEL,
                                 "a508bb932959c")

    theProject.projTree[hHandle].itemLayout == nwItemLayout.DOCUMENT
    theProject.projTree[sHandle].itemLayout == nwItemLayout.DOCUMENT
    theProject.projTree[tHandle].itemLayout == nwItemLayout.DOCUMENT

    assert theIndex.scanText(hHandle, "## Chapter One\n\n")
    assert theIndex.scanText(sHandle, "### Scene One\n\n")
    assert theIndex.scanText(tHandle, "### Scene Two\n\n")

    assert theIndex._listNovelHandles(False) == [
        nHandle, hHandle, sHandle, tHandle
    ]
    assert theIndex._listNovelHandles(True) == [hHandle, sHandle, tHandle]

    # Add a fake handle to the tree and check that it's ignored
    theProject.projTree._treeOrder.append("0000000000000")
    assert theIndex._listNovelHandles(False) == [
        nHandle, hHandle, sHandle, tHandle
    ]
    theProject.projTree._treeOrder.remove("0000000000000")

    # Extract stats
    assert theIndex.getNovelWordCount(False) == 34
    assert theIndex.getNovelWordCount(True) == 6
    assert theIndex.getNovelTitleCounts(False) == [0, 2, 1, 2, 0]
    assert theIndex.getNovelTitleCounts(True) == [0, 0, 1, 2, 0]

    # Table of Contents
    assert theIndex.getTableOfContents(0, True) == []
    assert theIndex.getTableOfContents(1, True) == []
    assert theIndex.getTableOfContents(2, True) == [
        ("%s:T000001" % hHandle, 2, "Chapter One", 6),
    ]
    assert theIndex.getTableOfContents(3, True) == [
        ("%s:T000001" % hHandle, 2, "Chapter One", 2),
        ("%s:T000001" % sHandle, 3, "Scene One", 2),
        ("%s:T000001" % tHandle, 3, "Scene Two", 2),
    ]

    assert theIndex.getTableOfContents(0, False) == []
    assert theIndex.getTableOfContents(1, False) == [
        ("%s:T000001" % nHandle, 1, "Hello World!", 12),
        ("%s:T000011" % nHandle, 1, "Hello World!", 22),
    ]

    # Header Word Counts
    bHandle = "0000000000000"
    assert theIndex.getHandleWordCounts(bHandle) == []
    assert theIndex.getHandleWordCounts(hHandle) == [("%s:T000001" % hHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(sHandle) == [("%s:T000001" % sHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(tHandle) == [("%s:T000001" % tHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(nHandle) == [
        ("%s:T000001" % nHandle, 12), ("%s:T000011" % nHandle, 16)
    ]

    assert theProject.closeProject()

    # Header Record
    bHandle = "0000000000000"
    assert theIndex.getHandleHeaders(bHandle) == []
    assert theIndex.getHandleHeaders(hHandle) == [("T000001", "H2",
                                                   "Chapter One")]
    assert theIndex.getHandleHeaders(sHandle) == [("T000001", "H3",
                                                   "Scene One")]
    assert theIndex.getHandleHeaders(tHandle) == [("T000001", "H3",
                                                   "Scene Two")]
    assert theIndex.getHandleHeaders(nHandle) == [
        ("T000001", "H1", "Hello World!"), ("T000011", "H1", "Hello World!")
    ]
Пример #4
0
def testCoreIndex_ScanText(nwMinimal, mockGUI):
    """Check the index text scanner.
    """
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal) is True

    theIndex = NWIndex(theProject)

    # Some items for fail to scan tests
    dHandle = theProject.newFolder("Folder", nwItemClass.NOVEL,
                                   "a508bb932959c")
    xHandle = theProject.newFile("No Layout", nwItemClass.NOVEL,
                                 "a508bb932959c")
    xItem = theProject.projTree[xHandle]
    xItem.setLayout(nwItemLayout.NO_LAYOUT)

    # Check invalid data
    assert theIndex.scanText(None, "Hello World!") is False
    assert theIndex.scanText(dHandle, "Hello World!") is False
    assert theIndex.scanText(xHandle, "Hello World!") is False

    xItem.setLayout(nwItemLayout.DOCUMENT)
    xItem.setParent(None)
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Create the trash folder
    tHandle = theProject.trashFolder()
    assert theProject.projTree[tHandle] is not None
    xItem.setParent(tHandle)
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Create the archive root
    aHandle = theProject.newRoot("Archive", nwItemClass.ARCHIVE)
    assert theProject.projTree[aHandle] is not None
    xItem.setParent(aHandle)
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Make some usable items
    tHandle = theProject.newFile("Title", nwItemClass.NOVEL, "a508bb932959c")
    pHandle = theProject.newFile("Page", nwItemClass.NOVEL, "a508bb932959c")
    nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
    cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER,
                                 "afb3043c7b2b3")
    sHandle = theProject.newFile("Scene", nwItemClass.NOVEL, "a508bb932959c")

    # Text Indexing
    # =============

    # Index correct text
    assert theIndex.scanText(cHandle, ("# Jane Smith\n" "@tag: Jane\n"))
    assert theIndex.scanText(nHandle, ("# Hello World!\n"
                                       "@pov: Jane\n"
                                       "@char: Jane\n\n"
                                       "% this is a comment\n\n"
                                       "This is a story about Jane Smith.\n\n"
                                       "Well, not really.\n"))
    assert theIndex._tagIndex == {"Jane": [2, cHandle, "CHARACTER", "T000001"]}
    assert theIndex.getNovelData(nHandle, "T000001")["title"] == "Hello World!"

    # Title Indexing
    # ==============

    # Document File
    assert theIndex.scanText(
        nHandle,
        (
            "# Title One\n\n"
            "% synopsis: Synopsis One.\n\n"
            "Paragraph One.\n\n"
            "## Title Two\n\n"
            "% synopsis: Synopsis Two.\n\n"
            "Paragraph Two.\n\n"
            "### Title Three\n\n"
            "% synopsis: Synopsis Three.\n\n"
            "Paragraph Three.\n\n"
            "#### Title Four\n\n"
            "% synopsis: Synopsis Four.\n\n"
            "Paragraph Four.\n\n"
            "##### Title Five\n\n"  # Not interpreted as a title, the hashes are counted as a word
            "Paragraph Five.\n\n"))
    assert nHandle not in theIndex._refIndex

    assert theIndex._fileIndex[nHandle]["T000001"]["level"] == "H1"
    assert theIndex._fileIndex[nHandle]["T000007"]["level"] == "H2"
    assert theIndex._fileIndex[nHandle]["T000013"]["level"] == "H3"
    assert theIndex._fileIndex[nHandle]["T000019"]["level"] == "H4"

    assert theIndex._fileIndex[nHandle]["T000001"]["title"] == "Title One"
    assert theIndex._fileIndex[nHandle]["T000007"]["title"] == "Title Two"
    assert theIndex._fileIndex[nHandle]["T000013"]["title"] == "Title Three"
    assert theIndex._fileIndex[nHandle]["T000019"]["title"] == "Title Four"

    assert theIndex._fileIndex[nHandle]["T000001"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[nHandle]["T000007"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[nHandle]["T000013"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[nHandle]["T000019"]["layout"] == "DOCUMENT"

    assert theIndex._fileIndex[nHandle]["T000001"]["cCount"] == 23
    assert theIndex._fileIndex[nHandle]["T000007"]["cCount"] == 23
    assert theIndex._fileIndex[nHandle]["T000013"]["cCount"] == 27
    assert theIndex._fileIndex[nHandle]["T000019"]["cCount"] == 56

    assert theIndex._fileIndex[nHandle]["T000001"]["wCount"] == 4
    assert theIndex._fileIndex[nHandle]["T000007"]["wCount"] == 4
    assert theIndex._fileIndex[nHandle]["T000013"]["wCount"] == 4
    assert theIndex._fileIndex[nHandle]["T000019"]["wCount"] == 9

    assert theIndex._fileIndex[nHandle]["T000001"]["pCount"] == 1
    assert theIndex._fileIndex[nHandle]["T000007"]["pCount"] == 1
    assert theIndex._fileIndex[nHandle]["T000013"]["pCount"] == 1
    assert theIndex._fileIndex[nHandle]["T000019"]["pCount"] == 3

    assert theIndex._fileIndex[nHandle]["T000001"][
        "synopsis"] == "Synopsis One."
    assert theIndex._fileIndex[nHandle]["T000007"][
        "synopsis"] == "Synopsis Two."
    assert theIndex._fileIndex[nHandle]["T000013"][
        "synopsis"] == "Synopsis Three."
    assert theIndex._fileIndex[nHandle]["T000019"][
        "synopsis"] == "Synopsis Four."

    # Note File
    assert theIndex.scanText(cHandle, ("# Title One\n\n"
                                       "@tag: One\n\n"
                                       "% synopsis: Synopsis One.\n\n"
                                       "Paragraph One.\n\n"))
    assert cHandle not in theIndex._refIndex

    assert theIndex._fileIndex[cHandle]["T000001"]["level"] == "H1"
    assert theIndex._fileIndex[cHandle]["T000001"]["title"] == "Title One"
    assert theIndex._fileIndex[cHandle]["T000001"]["layout"] == "NOTE"
    assert theIndex._fileIndex[cHandle]["T000001"]["cCount"] == 23
    assert theIndex._fileIndex[cHandle]["T000001"]["wCount"] == 4
    assert theIndex._fileIndex[cHandle]["T000001"]["pCount"] == 1
    assert theIndex._fileIndex[cHandle]["T000001"][
        "synopsis"] == "Synopsis One."

    # Valid and Invalid References
    assert theIndex.scanText(
        sHandle,
        (
            "# Title One\n\n"
            "@pov: One\n\n"  # Valid
            "@char: Two\n\n"  # Invalid tag
            "@:\n\n"  # Invalid line
            "% synopsis: Synopsis One.\n\n"
            "Paragraph One.\n\n"))
    assert theIndex._refIndex[sHandle]["T000001"] == ([[3, "@pov", "One"],
                                                       [5, "@char", "Two"]])

    # Special Titles
    # ==============

    assert theIndex.scanText(tHandle, ("#! My Project\n\n"
                                       ">> By Jane Doe <<\n\n"))
    assert tHandle not in theIndex._refIndex

    assert theIndex._fileIndex[tHandle]["T000001"]["level"] == "H1"
    assert theIndex._fileIndex[tHandle]["T000001"]["title"] == "My Project"
    assert theIndex._fileIndex[tHandle]["T000001"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[tHandle]["T000001"]["cCount"] == 21
    assert theIndex._fileIndex[tHandle]["T000001"]["wCount"] == 5
    assert theIndex._fileIndex[tHandle]["T000001"]["pCount"] == 1
    assert theIndex._fileIndex[tHandle]["T000001"]["synopsis"] == ""

    assert theIndex.scanText(tHandle,
                             ("##! Prologue\n\n"
                              "In the beginning there was time ...\n\n"))
    assert tHandle not in theIndex._refIndex

    assert theIndex._fileIndex[tHandle]["T000001"]["level"] == "H2"
    assert theIndex._fileIndex[tHandle]["T000001"]["title"] == "Prologue"
    assert theIndex._fileIndex[tHandle]["T000001"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[tHandle]["T000001"]["cCount"] == 43
    assert theIndex._fileIndex[tHandle]["T000001"]["wCount"] == 8
    assert theIndex._fileIndex[tHandle]["T000001"]["pCount"] == 1
    assert theIndex._fileIndex[tHandle]["T000001"]["synopsis"] == ""

    # Page wo/Title
    # =============

    theProject.projTree[pHandle]._layout = nwItemLayout.DOCUMENT
    assert theIndex.scanText(pHandle,
                             ("This is a page with some text on it.\n\n"))
    assert pHandle in theIndex._fileIndex
    assert theIndex._fileIndex[pHandle]["T000000"]["level"] == "H0"
    assert theIndex._fileIndex[pHandle]["T000000"]["title"] == ""
    assert theIndex._fileIndex[pHandle]["T000000"]["layout"] == "DOCUMENT"
    assert theIndex._fileIndex[pHandle]["T000000"]["cCount"] == 36
    assert theIndex._fileIndex[pHandle]["T000000"]["wCount"] == 9
    assert theIndex._fileIndex[pHandle]["T000000"]["pCount"] == 1
    assert theIndex._fileIndex[pHandle]["T000000"]["synopsis"] == ""

    theProject.projTree[pHandle]._layout = nwItemLayout.NOTE
    assert theIndex.scanText(pHandle,
                             ("This is a page with some text on it.\n\n"))
    assert pHandle in theIndex._fileIndex
    assert theIndex._fileIndex[pHandle]["T000000"]["level"] == "H0"
    assert theIndex._fileIndex[pHandle]["T000000"]["title"] == ""
    assert theIndex._fileIndex[pHandle]["T000000"]["layout"] == "NOTE"
    assert theIndex._fileIndex[pHandle]["T000000"]["cCount"] == 36
    assert theIndex._fileIndex[pHandle]["T000000"]["wCount"] == 9
    assert theIndex._fileIndex[pHandle]["T000000"]["pCount"] == 1
    assert theIndex._fileIndex[pHandle]["T000000"]["synopsis"] == ""

    assert theProject.closeProject() is True
Пример #5
0
def testCoreIndex_CheckThese(nwMinimal, mockGUI):
    """Test the tag checker function checkThese.
    """
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal) is True

    theIndex = NWIndex(theProject)
    nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
    cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER,
                                 "afb3043c7b2b3")
    nItem = theProject.projTree[nHandle]
    cItem = theProject.projTree[cHandle]

    assert theIndex.novelChangedSince(0) is False
    assert theIndex.notesChangedSince(0) is False
    assert theIndex.indexChangedSince(0) is False

    assert theIndex.scanText(cHandle, ("# Jane Smith\n"
                                       "@tag: Jane\n"
                                       "@tag:\n"
                                       "@:\n"))
    assert theIndex.scanText(
        nHandle,
        (
            "# Hello World!\n"
            "@pov: Jane\n"
            "@invalid: John\n"  # Checks for issue #688
        ))
    assert theIndex._tagIndex == {"Jane": [2, cHandle, "CHARACTER", "T000001"]}
    assert theIndex.getNovelData(nHandle, "T000001")["title"] == "Hello World!"
    assert theIndex.getReferences(nHandle, "T000001") == {
        "@char": [],
        "@custom": [],
        "@entity": [],
        "@focus": [],
        "@location": [],
        "@object": [],
        "@plot": [],
        "@pov": ["Jane"],
        "@time": []
    }

    assert theIndex.novelChangedSince(0) is True
    assert theIndex.notesChangedSince(0) is True
    assert theIndex.indexChangedSince(0) is True

    assert theIndex.getHandleHeaderLevel(cHandle) == "H1"
    assert theIndex.getHandleHeaderLevel(nHandle) == "H1"

    # Zero Items
    assert theIndex.checkThese([], cItem) == []

    # One Item
    assert theIndex.checkThese(["@tag"], cItem) == [True]
    assert theIndex.checkThese(["@who"], cItem) == [False]

    # Two Items
    assert theIndex.checkThese(["@tag", "Jane"], cItem) == [True, True]
    assert theIndex.checkThese(["@tag", "John"], cItem) == [True, True]
    assert theIndex.checkThese(["@tag", "Jane"], nItem) == [True, False]
    assert theIndex.checkThese(["@tag", "John"], nItem) == [True, True]
    assert theIndex.checkThese(["@pov", "John"], nItem) == [True, False]
    assert theIndex.checkThese(["@pov", "Jane"], nItem) == [True, True]
    assert theIndex.checkThese(["@ pov", "Jane"], nItem) == [False, False]
    assert theIndex.checkThese(["@what", "Jane"], nItem) == [False, False]

    # Three Items
    assert theIndex.checkThese(["@tag", "Jane", "John"],
                               cItem) == [True, True, False]
    assert theIndex.checkThese(["@who", "Jane", "John"],
                               cItem) == [False, False, False]
    assert theIndex.checkThese(["@pov", "Jane", "John"],
                               nItem) == [True, True, False]

    assert theProject.closeProject() is True
Пример #6
0
def testCoreProject_Methods(monkeypatch, nwMinimal, mockGUI, tmpDir):
    """Test other project class methods and functions.
    """
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)
    assert theProject.projPath == nwMinimal

    # Setting project path
    assert theProject.setProjectPath(None)
    assert theProject.projPath is None
    assert theProject.setProjectPath("")
    assert theProject.projPath is None
    assert theProject.setProjectPath("~")
    assert theProject.projPath == os.path.expanduser("~")

    # Create a new folder and populate it
    projPath = os.path.join(nwMinimal, "mock1")
    assert theProject.setProjectPath(projPath, newProject=True)

    # Make os.mkdir fail
    monkeypatch.setattr("os.mkdir", causeOSError)
    projPath = os.path.join(nwMinimal, "mock2")
    assert not theProject.setProjectPath(projPath, newProject=True)

    # Set back
    assert theProject.setProjectPath(nwMinimal)

    # Project Name
    assert theProject.setProjectName("  A Name ")
    assert theProject.projName == "A Name"

    # Project Title
    assert theProject.setBookTitle("  A Title ")
    assert theProject.bookTitle == "A Title"

    # Project Authors
    # Check that the list is cleaned up and that it can be extracted as
    # a properly formatted string, depending on number of names
    assert not theProject.setBookAuthors([])
    assert theProject.setBookAuthors(" Jane Doe \n John Doh \n ")
    assert theProject.bookAuthors == ["Jane Doe", "John Doh"]

    assert theProject.setBookAuthors("")
    assert theProject.getAuthors() == ""

    assert theProject.setBookAuthors("Jane Doe")
    assert theProject.getAuthors() == "Jane Doe"

    assert theProject.setBookAuthors("Jane Doe\nJohn Doh")
    assert theProject.getAuthors() == "Jane Doe and John Doh"

    assert theProject.setBookAuthors("Jane Doe\nJohn Doh\nBod Owens")
    assert theProject.getAuthors() == "Jane Doe, John Doh and Bod Owens"

    # Edit Time
    theProject.editTime = 1234
    theProject.projOpened = 1600000000
    with monkeypatch.context() as mp:
        mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
        assert theProject.getCurrentEditTime() == 6834

    # Trash folder
    # Should create on first call, and just returned on later calls
    assert theProject.projTree["73475cb40a568"] is None
    assert theProject.trashFolder() == "73475cb40a568"
    assert theProject.trashFolder() == "73475cb40a568"

    # Project backup
    assert theProject.doBackup is True
    assert theProject.setProjBackup(False)
    assert theProject.doBackup is False

    assert not theProject.setProjBackup(True)
    theProject.mainConf.backupPath = tmpDir
    assert theProject.setProjBackup(True)

    assert theProject.setProjectName("")
    assert not theProject.setProjBackup(True)
    assert theProject.setProjectName("A Name")
    assert theProject.setProjBackup(True)

    # Spell check
    theProject.projChanged = False
    assert theProject.setSpellCheck(True)
    assert not theProject.setSpellCheck(False)
    assert theProject.projChanged

    # Spell language
    theProject.projChanged = False
    assert theProject.setSpellLang(None)
    assert theProject.projSpell is None
    assert theProject.setSpellLang("None")
    assert theProject.projSpell is None
    assert theProject.setSpellLang("en_GB")
    assert theProject.projSpell == "en_GB"
    assert theProject.projChanged

    # Project Language
    theProject.projChanged = False
    theProject.projLang = "en"
    assert theProject.setProjectLang(None) is True
    assert theProject.projLang is None
    assert theProject.setProjectLang("en_GB") is True
    assert theProject.projLang == "en_GB"

    # Automatic outline update
    theProject.projChanged = False
    assert theProject.setAutoOutline(True)
    assert not theProject.setAutoOutline(False)
    assert theProject.projChanged

    # Last edited
    theProject.projChanged = False
    assert theProject.setLastEdited("0123456789abc")
    assert theProject.lastEdited == "0123456789abc"
    assert theProject.projChanged

    # Last viewed
    theProject.projChanged = False
    assert theProject.setLastViewed("0123456789abc")
    assert theProject.lastViewed == "0123456789abc"
    assert theProject.projChanged

    # Autoreplace
    theProject.projChanged = False
    assert theProject.setAutoReplace({"A": "B", "C": "D"})
    assert theProject.autoReplace == {"A": "B", "C": "D"}
    assert theProject.projChanged

    # Change project tree order
    oldOrder = [
        "a508bb932959c",
        "a35baf2e93843",
        "a6d311a93600a",
        "f5ab3e30151e1",
        "8c659a11cd429",
        "7695ce551d265",
        "afb3043c7b2b3",
        "9d5247ab588e0",
        "73475cb40a568",
    ]
    newOrder = [
        "f5ab3e30151e1",
        "8c659a11cd429",
        "7695ce551d265",
        "a508bb932959c",
        "a35baf2e93843",
        "a6d311a93600a",
        "afb3043c7b2b3",
        "9d5247ab588e0",
    ]
    assert theProject.projTree.handles() == oldOrder
    assert theProject.setTreeOrder(newOrder)
    assert theProject.projTree.handles() == newOrder
    assert theProject.setTreeOrder(oldOrder)
    assert theProject.projTree.handles() == oldOrder

    # Change status
    theProject.projTree["a35baf2e93843"].setStatus("Finished")
    theProject.projTree["a6d311a93600a"].setStatus("Draft")
    theProject.projTree["f5ab3e30151e1"].setStatus("Note")
    theProject.projTree["8c659a11cd429"].setStatus("Finished")
    newList = [
        ("New", 1, 1, 1, "New"),
        ("Draft", 2, 2, 2, "Note"),  # These are swapped
        ("Note", 3, 3, 3, "Draft"),  # These are swapped
        ("Edited", 4, 4, 4, "Finished"),  # Renamed
        ("Finished", 5, 5, 5, None),  # New, with reused name
    ]
    assert theProject.setStatusColours(newList)
    assert theProject.statusItems._theLabels == [
        "New", "Draft", "Note", "Edited", "Finished"
    ]
    assert theProject.statusItems._theColours == [(1, 1, 1), (2, 2, 2),
                                                  (3, 3, 3), (4, 4, 4),
                                                  (5, 5, 5)]
    assert theProject.projTree[
        "a35baf2e93843"].itemStatus == "Edited"  # Renamed
    assert theProject.projTree["a6d311a93600a"].itemStatus == "Note"  # Swapped
    assert theProject.projTree["f5ab3e30151e1"].itemStatus == "Draft"  # Swapped
    assert theProject.projTree[
        "8c659a11cd429"].itemStatus == "Edited"  # Renamed

    # Change importance
    fHandle = theProject.newFile("Jane Doe", nwItemClass.CHARACTER,
                                 "afb3043c7b2b3")
    theProject.projTree[fHandle].setImport("Main")
    newList = [
        ("New", 1, 1, 1, "New"),
        ("Minor", 2, 2, 2, "Minor"),
        ("Major", 3, 3, 3, "Major"),
        ("Min", 4, 4, 4, "Main"),
        ("Max", 5, 5, 5, None),
    ]
    assert theProject.setImportColours(newList)
    assert theProject.importItems._theLabels == [
        "New", "Minor", "Major", "Min", "Max"
    ]
    assert theProject.importItems._theColours == [(1, 1, 1), (2, 2, 2),
                                                  (3, 3, 3), (4, 4, 4),
                                                  (5, 5, 5)]
    assert theProject.projTree[fHandle].itemImport == "Min"

    # Check status counts
    assert theProject.statusItems._theCounts == [0, 0, 0, 0, 0]
    assert theProject.importItems._theCounts == [0, 0, 0, 0, 0]
    theProject.countStatus()
    assert theProject.statusItems._theCounts == [1, 1, 1, 2, 0]
    assert theProject.importItems._theCounts == [3, 0, 0, 1, 0]

    # Session stats
    theProject.currWCount = 200
    theProject.lastWCount = 100
    with monkeypatch.context() as mp:
        mp.setattr("os.path.isdir", lambda *a, **k: False)
        assert not theProject._appendSessionStats(idleTime=0)

    # Block open
    with monkeypatch.context() as mp:
        mp.setattr("builtins.open", causeOSError)
        assert not theProject._appendSessionStats(idleTime=0)

    # Write entry
    assert theProject.projMeta == os.path.join(nwMinimal, "meta")
    statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS)

    theProject.projOpened = 1600002000
    theProject.currNovelWC = 200
    theProject.currNotesWC = 100

    with monkeypatch.context() as mp:
        mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
        assert theProject._appendSessionStats(idleTime=99)

    assert readFile(statsFile) == (
        "# Offset 100\n"
        "# Start Time         End Time                Novel     Notes      Idle\n"
        "%s  %s       200       100        99\n") % (
            formatTimeStamp(1600002000), formatTimeStamp(1600005600))

    # Pack XML Value
    xElem = etree.Element("element")
    theProject._packProjectValue(xElem, "A", "B", allowNone=False)
    assert etree.tostring(xElem, pretty_print=False,
                          encoding="utf-8") == (b"<element><A>B</A></element>")

    xElem = etree.Element("element")
    theProject._packProjectValue(xElem, "A", "", allowNone=False)
    assert etree.tostring(xElem, pretty_print=False,
                          encoding="utf-8") == (b"<element/>")

    # Pack XML Key/Value
    xElem = etree.Element("element")
    theProject._packProjectKeyValue(xElem, "item", {"A": "B", "C": "D"})
    assert etree.tostring(xElem, pretty_print=False,
                          encoding="utf-8") == (b"<element>"
                                                b"<item>"
                                                b"<entry key=\"A\">B</entry>"
                                                b"<entry key=\"C\">D</entry>"
                                                b"</item>"
                                                b"</element>")
Пример #7
0
def testCoreIndex_ItemIndex(mockGUI, fncDir, mockRnd):
    """Check the ItemIndex class.
    """
    theProject = NWProject(mockGUI)
    buildTestProject(theProject, fncDir)

    nHandle = "0000000000014"
    cHandle = "0000000000016"
    sHandle = "0000000000017"

    assert theProject.index.saveIndex() is True
    itemIndex = theProject.index._itemIndex

    # The index should be empty
    assert nHandle not in itemIndex
    assert cHandle not in itemIndex
    assert sHandle not in itemIndex

    # Add Items
    # =========
    assert cHandle not in itemIndex

    # Add the novel chapter file
    itemIndex.add(cHandle, theProject.tree[cHandle])
    assert cHandle in itemIndex
    assert itemIndex[cHandle].item == theProject.tree[cHandle]
    assert itemIndex.mainItemHeader(cHandle) == "H0"
    assert itemIndex.allItemTags(cHandle) == []
    assert list(itemIndex.iterItemHeaders(cHandle))[0][0] == "T000000"

    # Add a heading to the item, which should replace the T000000 heading
    itemIndex.addItemHeading(cHandle, "T000001", "H2", "Chapter One")
    assert itemIndex.mainItemHeader(cHandle) == "H2"
    assert list(itemIndex.iterItemHeaders(cHandle))[0][0] == "T000001"

    # Set the remainig data values
    itemIndex.setHeadingCounts(cHandle, "T000001", 60, 10, 2)
    itemIndex.setHeadingSynopsis(cHandle, "T000001", "In the beginning ...")
    itemIndex.setHeadingTag(cHandle, "T000001", "One")
    itemIndex.addHeadingReferences(cHandle, "T000001", ["Jane"], "@pov")
    itemIndex.addHeadingReferences(cHandle, "T000001", ["Jane"], "@focus")
    itemIndex.addHeadingReferences(cHandle, "T000001", ["Jane", "John"],
                                   "@char")
    idxData = itemIndex.packData()

    assert idxData[cHandle]["level"] == "H2"
    assert idxData[cHandle]["headings"]["T000001"] == {
        "level": "H2",
        "title": "Chapter One",
        "tag": "One",
        "cCount": 60,
        "wCount": 10,
        "pCount": 2,
        "synopsis": "In the beginning ...",
    }
    assert "@pov" in idxData[cHandle]["references"]["T000001"]["Jane"]
    assert "@focus" in idxData[cHandle]["references"]["T000001"]["Jane"]
    assert "@char" in idxData[cHandle]["references"]["T000001"]["Jane"]
    assert "@char" in idxData[cHandle]["references"]["T000001"]["John"]

    # Add the other two files
    itemIndex.add(nHandle, theProject.tree[nHandle])
    itemIndex.add(sHandle, theProject.tree[sHandle])
    itemIndex.addItemHeading(nHandle, "T000001", "H1", "Novel")
    itemIndex.addItemHeading(sHandle, "T000001", "H3", "Scene One")

    # Check Item and Heading Direct Access
    # ====================================

    # Check repr strings
    assert repr(itemIndex[nHandle]) == f"<IndexItem handle='{nHandle}'>"
    assert repr(
        itemIndex[nHandle]["T000001"]) == "<IndexHeading key='T000001'>"

    # Check content of a single item
    assert "T000001" in itemIndex[nHandle]
    assert itemIndex[cHandle].allTags() == ["One"]

    # Check the content of a single heading
    assert itemIndex[cHandle]["T000001"].key == "T000001"
    assert itemIndex[cHandle]["T000001"].level == "H2"
    assert itemIndex[cHandle]["T000001"].title == "Chapter One"
    assert itemIndex[cHandle]["T000001"].tag == "One"
    assert itemIndex[cHandle]["T000001"].charCount == 60
    assert itemIndex[cHandle]["T000001"].wordCount == 10
    assert itemIndex[cHandle]["T000001"].paraCount == 2
    assert itemIndex[cHandle]["T000001"].synopsis == "In the beginning ..."
    assert "Jane" in itemIndex[cHandle]["T000001"].references
    assert "John" in itemIndex[cHandle]["T000001"].references

    # Check heading level setter
    itemIndex[cHandle]["T000001"].setLevel("H3")  # Change it
    assert itemIndex[cHandle]["T000001"].level == "H3"
    itemIndex[cHandle]["T000001"].setLevel("H2")  # Set it back
    assert itemIndex[cHandle]["T000001"].level == "H2"
    itemIndex[cHandle]["T000001"].setLevel("H5")  # Invalid level
    assert itemIndex[cHandle]["T000001"].level == "H2"

    # Data Extraction
    # ===============

    # Get headers
    allHeads = list(itemIndex.iterAllHeaders())
    assert allHeads[0][0] == cHandle
    assert allHeads[1][0] == nHandle
    assert allHeads[2][0] == sHandle
    assert allHeads[0][1] == "T000001"
    assert allHeads[1][1] == "T000001"
    assert allHeads[2][1] == "T000001"

    # Ask for stuff that doesn't exist
    assert itemIndex.mainItemHeader("blablabla") == "H0"
    assert itemIndex.allItemTags("blablabla") == []

    # Novel Structure
    # ===============

    # Add a second novel
    mHandle = theProject.newRoot(nwItemClass.NOVEL)
    uHandle = theProject.newFile("Title Page", mHandle)
    itemIndex.add(uHandle, theProject.tree[uHandle])
    itemIndex.addItemHeading(uHandle, "T000001", "H1", "Novel 2")
    assert uHandle in itemIndex

    # Structure of all novels
    nStruct = list(itemIndex.iterNovelStructure())
    assert len(nStruct) == 4
    assert nStruct[0][0] == nHandle
    assert nStruct[1][0] == cHandle
    assert nStruct[2][0] == sHandle
    assert nStruct[3][0] == uHandle

    # Novel structure with root handle set
    nStruct = list(itemIndex.iterNovelStructure(rootHandle="0000000000010"))
    assert len(nStruct) == 3
    assert nStruct[0][0] == nHandle
    assert nStruct[1][0] == cHandle
    assert nStruct[2][0] == sHandle

    nStruct = list(itemIndex.iterNovelStructure(rootHandle=mHandle))
    assert len(nStruct) == 1
    assert nStruct[0][0] == uHandle

    # Inject garbage into tree
    theProject.tree._treeOrder.append("stuff")
    nStruct = list(itemIndex.iterNovelStructure())
    assert len(nStruct) == 4
    assert nStruct[0][0] == nHandle
    assert nStruct[1][0] == cHandle
    assert nStruct[2][0] == sHandle
    assert nStruct[3][0] == uHandle

    # Skip excluded
    theProject.tree[sHandle].setExported(False)
    nStruct = list(itemIndex.iterNovelStructure(skipExcl=True))
    assert len(nStruct) == 3
    assert nStruct[0][0] == nHandle
    assert nStruct[1][0] == cHandle
    assert nStruct[2][0] == uHandle

    # Delete new item
    del itemIndex[uHandle]
    assert uHandle not in itemIndex

    # Unpack Error Handling
    # =====================

    # Pack/unpack should restore state
    content = itemIndex.packData()
    itemIndex.clear()
    itemIndex.unpackData(content)
    assert itemIndex.packData() == content
    itemIndex.clear()

    # Data must be dictionary
    with pytest.raises(ValueError):
        itemIndex.unpackData("stuff")

    # Keys must be valid handles
    with pytest.raises(ValueError):
        itemIndex.unpackData({"stuff": "more stuff"})

    # Unknown keys should be skipped
    itemIndex.unpackData({"0000000000000": {}})
    assert itemIndex._items == {}

    # Known keys can be added, even witout data
    itemIndex.unpackData({nHandle: {}})
    assert nHandle in itemIndex

    # Title tags must be valid
    with pytest.raises(ValueError):
        itemIndex.unpackData({cHandle: {"headings": {"TTTTTTT": {}}}})

    # Reference without a heading should be rejected
    itemIndex.unpackData({
        cHandle: {
            "headings": {
                "T000001": {}
            },
            "references": {
                "T000001": {},
                "T000002": {}
            },
        }
    })
    assert "T000001" in itemIndex[cHandle]
    assert "T000002" not in itemIndex[cHandle]
    itemIndex.clear()

    # Tag keys must be strings
    with pytest.raises(ValueError):
        itemIndex.unpackData({
            cHandle: {
                "headings": {
                    "T000001": {}
                },
                "references": {
                    "T000001": {
                        1234: "@pov"
                    }
                },
            }
        })

    # Type must be strings
    with pytest.raises(ValueError):
        itemIndex.unpackData({
            cHandle: {
                "headings": {
                    "T000001": {}
                },
                "references": {
                    "T000001": {
                        "John": []
                    }
                },
            }
        })

    # Types must be valid
    with pytest.raises(ValueError):
        itemIndex.unpackData({
            cHandle: {
                "headings": {
                    "T000001": {}
                },
                "references": {
                    "T000001": {
                        "John": "@pov,@char,@stuff"
                    }
                },
            }
        })

    # This should pass
    itemIndex.unpackData({
        cHandle: {
            "headings": {
                "T000001": {}
            },
            "references": {
                "T000001": {
                    "John": "@pov,@char"
                }
            },
        }
    })
Пример #8
0
def testCoreIndex_ExtractData(mockGUI, fncDir, mockRnd):
    """Check the index data extraction functions.
    """
    theProject = NWProject(mockGUI)
    buildTestProject(theProject, fncDir)

    theIndex = theProject.index
    theIndex.reIndexHandle("0000000000010")
    theIndex.reIndexHandle("0000000000011")
    theIndex.reIndexHandle("0000000000012")
    theIndex.reIndexHandle("0000000000013")
    theIndex.reIndexHandle("0000000000014")
    theIndex.reIndexHandle("0000000000015")
    theIndex.reIndexHandle("0000000000016")
    theIndex.reIndexHandle("0000000000017")

    nHandle = theProject.newFile("Hello", "0000000000010")
    cHandle = theProject.newFile("Jane", "0000000000012")

    assert theIndex.getNovelData("", "") is None
    assert theIndex.getNovelData("0000000000010", "") is None

    assert theIndex.scanText(cHandle, ("# Jane Smith\n" "@tag: Jane\n"))
    assert theIndex.scanText(nHandle, ("# Hello World!\n"
                                       "@pov: Jane\n"
                                       "@char: Jane\n\n"
                                       "% this is a comment\n\n"
                                       "This is a story about Jane Smith.\n\n"
                                       "Well, not really.\n"))

    # The novel structure should contain the pointer to the novel file header
    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure():
        theKeys.append(aKey)

    assert theKeys == [
        "0000000000014:T000001",
        "0000000000016:T000001",
        "0000000000017:T000001",
        "%s:T000001" % nHandle,
    ]

    # Check that excluded files can be skipped
    theProject.tree[nHandle].setExported(False)

    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure(skipExcl=False):
        theKeys.append(aKey)

    assert theKeys == [
        "0000000000014:T000001",
        "0000000000016:T000001",
        "0000000000017:T000001",
        "%s:T000001" % nHandle,
    ]

    theKeys = []
    for aKey, _, _, _ in theIndex.novelStructure(skipExcl=True):
        theKeys.append(aKey)

    assert theKeys == [
        "0000000000014:T000001",
        "0000000000016:T000001",
        "0000000000017:T000001",
    ]

    # The novel file should have the correct counts
    cC, wC, pC = theIndex.getCounts(nHandle)
    assert cC == 62  # Characters in text and title only
    assert wC == 12  # Words in text and title only
    assert pC == 2  # Paragraphs in text only

    # getReferences
    # =============

    # Look up an ivalid handle
    theRefs = theIndex.getReferences("Not a handle")
    assert theRefs["@pov"] == []
    assert theRefs["@char"] == []

    # The novel file should now refer to Jane as @pov and @char
    theRefs = theIndex.getReferences(nHandle)
    assert theRefs["@pov"] == ["Jane"]
    assert theRefs["@char"] == ["Jane"]

    # getBackReferenceList
    # ====================

    # None handle should return an empty dict
    assert theIndex.getBackReferenceList(None) == {}

    # The Title Page file should have no references as it has no tag
    assert theIndex.getBackReferenceList("0000000000014") == {}

    # The character file should have a record of the reference from the novel file
    theRefs = theIndex.getBackReferenceList(cHandle)
    assert theRefs == {nHandle: "T000001"}

    # getTagSource
    # ============

    assert theIndex.getTagSource("Jane") == (cHandle, "T000001")
    assert theIndex.getTagSource("John") == (None, "T000000")

    # getCounts
    # =========
    # For whole text and sections

    # Invalid handle or title should return 0s
    assert theIndex.getCounts("stuff") == (0, 0, 0)
    assert theIndex.getCounts(nHandle, "stuff") == (0, 0, 0)

    # Get section counts for a novel file
    assert theIndex.scanText(
        nHandle, ("# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really.\n\n"
                  "# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really. She's still awesome though.\n"))
    # Whole document
    cC, wC, pC = theIndex.getCounts(nHandle)
    assert cC == 152
    assert wC == 28
    assert pC == 4

    # First part
    cC, wC, pC = theIndex.getCounts(nHandle, "T000001")
    assert cC == 62
    assert wC == 12
    assert pC == 2

    # Second part
    cC, wC, pC = theIndex.getCounts(nHandle, "T000011")
    assert cC == 90
    assert wC == 16
    assert pC == 2

    # Get section counts for a note file
    assert theIndex.scanText(
        cHandle, ("# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really.\n\n"
                  "# Hello World!\n"
                  "@pov: Jane\n"
                  "@char: Jane\n\n"
                  "% this is a comment\n\n"
                  "This is a story about Jane Smith.\n\n"
                  "Well, not really. She's still awesome though.\n"))
    # Whole document
    cC, wC, pC = theIndex.getCounts(cHandle)
    assert cC == 152
    assert wC == 28
    assert pC == 4

    # First part
    cC, wC, pC = theIndex.getCounts(cHandle, "T000001")
    assert cC == 62
    assert wC == 12
    assert pC == 2

    # Second part
    cC, wC, pC = theIndex.getCounts(cHandle, "T000011")
    assert cC == 90
    assert wC == 16
    assert pC == 2

    # Novel Stats
    # ===========

    hHandle = theProject.newFile("Chapter", "0000000000010")
    sHandle = theProject.newFile("Scene One", "0000000000010")
    tHandle = theProject.newFile("Scene Two", "0000000000010")

    theProject.tree[hHandle].itemLayout == nwItemLayout.DOCUMENT
    theProject.tree[sHandle].itemLayout == nwItemLayout.DOCUMENT
    theProject.tree[tHandle].itemLayout == nwItemLayout.DOCUMENT

    assert theIndex.scanText(hHandle, "## Chapter One\n\n")
    assert theIndex.scanText(sHandle, "### Scene One\n\n")
    assert theIndex.scanText(tHandle, "### Scene Two\n\n")

    assert [
        (h, t)
        for h, t, _ in theIndex._itemIndex.iterNovelStructure(skipExcl=False)
    ] == [
        ("0000000000014", "T000001"),
        ("0000000000016", "T000001"),
        ("0000000000017", "T000001"),
        (nHandle, "T000001"),
        (nHandle, "T000011"),
        (hHandle, "T000001"),
        (sHandle, "T000001"),
        (tHandle, "T000001"),
    ]

    assert [
        (h, t)
        for h, t, _ in theIndex._itemIndex.iterNovelStructure(skipExcl=True)
    ] == [
        ("0000000000014", "T000001"),
        ("0000000000016", "T000001"),
        ("0000000000017", "T000001"),
        (hHandle, "T000001"),
        (sHandle, "T000001"),
        (tHandle, "T000001"),
    ]

    # Add a fake handle to the tree and check that it's ignored
    theProject.tree._treeOrder.append("0000000000000")
    assert [
        (h, t)
        for h, t, _ in theIndex._itemIndex.iterNovelStructure(skipExcl=False)
    ] == [
        ("0000000000014", "T000001"),
        ("0000000000016", "T000001"),
        ("0000000000017", "T000001"),
        (nHandle, "T000001"),
        (nHandle, "T000011"),
        (hHandle, "T000001"),
        (sHandle, "T000001"),
        (tHandle, "T000001"),
    ]
    theProject.tree._treeOrder.remove("0000000000000")

    # Extract stats
    assert theIndex.getNovelWordCount(skipExcl=False) == 43
    assert theIndex.getNovelWordCount(skipExcl=True) == 15
    assert theIndex.getNovelTitleCounts(skipExcl=False) == [0, 3, 2, 3, 0]
    assert theIndex.getNovelTitleCounts(skipExcl=True) == [0, 1, 2, 3, 0]

    # Table of Contents
    assert theIndex.getTableOfContents(0, skipExcl=True) == []
    assert theIndex.getTableOfContents(1, skipExcl=True) == [
        ("0000000000014:T000001", 1, "New Novel", 15),
    ]
    assert theIndex.getTableOfContents(2, skipExcl=True) == [
        ("0000000000014:T000001", 1, "New Novel", 5),
        ("0000000000016:T000001", 2, "New Chapter", 4),
        ("%s:T000001" % hHandle, 2, "Chapter One", 6),
    ]
    assert theIndex.getTableOfContents(3, skipExcl=True) == [
        ("0000000000014:T000001", 1, "New Novel", 5),
        ("0000000000016:T000001", 2, "New Chapter", 2),
        ("0000000000017:T000001", 3, "New Scene", 2),
        ("%s:T000001" % hHandle, 2, "Chapter One", 2),
        ("%s:T000001" % sHandle, 3, "Scene One", 2),
        ("%s:T000001" % tHandle, 3, "Scene Two", 2),
    ]

    assert theIndex.getTableOfContents(0, skipExcl=False) == []
    assert theIndex.getTableOfContents(1, skipExcl=False) == [
        ("0000000000014:T000001", 1, "New Novel", 9),
        ("%s:T000001" % nHandle, 1, "Hello World!", 12),
        ("%s:T000011" % nHandle, 1, "Hello World!", 22),
    ]

    # Header Word Counts
    bHandle = "0000000000000"
    assert theIndex.getHandleWordCounts(bHandle) == []
    assert theIndex.getHandleWordCounts(hHandle) == [("%s:T000001" % hHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(sHandle) == [("%s:T000001" % sHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(tHandle) == [("%s:T000001" % tHandle,
                                                      2)]
    assert theIndex.getHandleWordCounts(nHandle) == [
        ("%s:T000001" % nHandle, 12), ("%s:T000011" % nHandle, 16)
    ]

    assert theIndex.saveIndex() is True
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True

    # Header Record
    bHandle = "0000000000000"
    assert theIndex.getHandleHeaders(bHandle) == []
    assert theIndex.getHandleHeaders(hHandle) == [("T000001", "H2",
                                                   "Chapter One")]
    assert theIndex.getHandleHeaders(sHandle) == [("T000001", "H3",
                                                   "Scene One")]
    assert theIndex.getHandleHeaders(tHandle) == [("T000001", "H3",
                                                   "Scene Two")]
    assert theIndex.getHandleHeaders(nHandle) == [
        ("T000001", "H1", "Hello World!"), ("T000011", "H1", "Hello World!")
    ]
Пример #9
0
def testCoreIndex_ScanText(mockGUI, fncDir, mockRnd):
    """Check the index text scanner.
    """
    theProject = NWProject(mockGUI)
    buildTestProject(theProject, fncDir)
    theIndex = theProject.index

    # Some items for fail to scan tests
    dHandle = theProject.newFolder("Folder", "0000000000010")
    xHandle = theProject.newFile("No Layout", "0000000000010")
    xItem = theProject.tree[xHandle]
    xItem.setLayout(nwItemLayout.NO_LAYOUT)

    # Check invalid data
    assert theIndex.scanText(None, "Hello World!") is False
    assert theIndex.scanText(dHandle, "Hello World!") is False
    assert theIndex.scanText(xHandle, "Hello World!") is False

    xItem.setLayout(nwItemLayout.DOCUMENT)
    xItem.setParent(None)
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Create the trash folder
    tHandle = theProject.trashFolder()
    assert theProject.tree[tHandle] is not None
    xItem.setParent(tHandle)
    theProject.tree.updateItemData(xItem.itemHandle)
    assert xItem.itemRoot == tHandle
    assert xItem.itemClass == nwItemClass.TRASH
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Create the archive root
    aHandle = theProject.newRoot(nwItemClass.ARCHIVE)
    assert theProject.tree[aHandle] is not None
    xItem.setParent(aHandle)
    theProject.tree.updateItemData(xItem.itemHandle)
    assert theIndex.scanText(xHandle, "Hello World!") is False

    # Make some usable items
    tHandle = theProject.newFile("Title", "0000000000010")
    pHandle = theProject.newFile("Page", "0000000000010")
    nHandle = theProject.newFile("Hello", "0000000000010")
    cHandle = theProject.newFile("Jane", "0000000000012")
    sHandle = theProject.newFile("Scene", "0000000000010")

    # Text Indexing
    # =============

    # Index correct text
    assert theIndex.scanText(cHandle, ("# Jane Smith\n" "@tag: Jane\n"))
    assert theIndex.scanText(nHandle, ("# Hello World!\n"
                                       "@pov: Jane\n"
                                       "@char: Jane\n\n"
                                       "% this is a comment\n\n"
                                       "This is a story about Jane Smith.\n\n"
                                       "Well, not really.\n"))
    assert theIndex._tagsIndex.tagHandle("Jane") == cHandle
    assert theIndex._tagsIndex.tagHeading("Jane") == "T000001"
    assert theIndex._tagsIndex.tagClass("Jane") == "CHARACTER"
    assert theIndex.getNovelData(nHandle, "T000001").title == "Hello World!"

    # Title Indexing
    # ==============

    # Document File
    assert theIndex.scanText(
        nHandle,
        (
            "# Title One\n\n"
            "% synopsis: Synopsis One.\n\n"
            "Paragraph One.\n\n"
            "## Title Two\n\n"
            "% synopsis: Synopsis Two.\n\n"
            "Paragraph Two.\n\n"
            "### Title Three\n\n"
            "% synopsis: Synopsis Three.\n\n"
            "Paragraph Three.\n\n"
            "#### Title Four\n\n"
            "% synopsis: Synopsis Four.\n\n"
            "Paragraph Four.\n\n"
            "##### Title Five\n\n"  # Not interpreted as a title, the hashes are counted as a word
            "Paragraph Five.\n\n"))
    assert theIndex._itemIndex[nHandle]["T000001"].references == {}
    assert theIndex._itemIndex[nHandle]["T000007"].references == {}
    assert theIndex._itemIndex[nHandle]["T000013"].references == {}
    assert theIndex._itemIndex[nHandle]["T000019"].references == {}

    assert theIndex._itemIndex[nHandle]["T000001"].level == "H1"
    assert theIndex._itemIndex[nHandle]["T000007"].level == "H2"
    assert theIndex._itemIndex[nHandle]["T000013"].level == "H3"
    assert theIndex._itemIndex[nHandle]["T000019"].level == "H4"

    assert theIndex._itemIndex[nHandle]["T000001"].title == "Title One"
    assert theIndex._itemIndex[nHandle]["T000007"].title == "Title Two"
    assert theIndex._itemIndex[nHandle]["T000013"].title == "Title Three"
    assert theIndex._itemIndex[nHandle]["T000019"].title == "Title Four"

    assert theIndex._itemIndex[nHandle]["T000001"].charCount == 23
    assert theIndex._itemIndex[nHandle]["T000007"].charCount == 23
    assert theIndex._itemIndex[nHandle]["T000013"].charCount == 27
    assert theIndex._itemIndex[nHandle]["T000019"].charCount == 56

    assert theIndex._itemIndex[nHandle]["T000001"].wordCount == 4
    assert theIndex._itemIndex[nHandle]["T000007"].wordCount == 4
    assert theIndex._itemIndex[nHandle]["T000013"].wordCount == 4
    assert theIndex._itemIndex[nHandle]["T000019"].wordCount == 9

    assert theIndex._itemIndex[nHandle]["T000001"].paraCount == 1
    assert theIndex._itemIndex[nHandle]["T000007"].paraCount == 1
    assert theIndex._itemIndex[nHandle]["T000013"].paraCount == 1
    assert theIndex._itemIndex[nHandle]["T000019"].paraCount == 3

    assert theIndex._itemIndex[nHandle]["T000001"].synopsis == "Synopsis One."
    assert theIndex._itemIndex[nHandle]["T000007"].synopsis == "Synopsis Two."
    assert theIndex._itemIndex[nHandle][
        "T000013"].synopsis == "Synopsis Three."
    assert theIndex._itemIndex[nHandle]["T000019"].synopsis == "Synopsis Four."

    # Note File
    assert theIndex.scanText(cHandle, ("# Title One\n\n"
                                       "@tag: One\n\n"
                                       "% synopsis: Synopsis One.\n\n"
                                       "Paragraph One.\n\n"))
    assert theIndex._itemIndex[cHandle]["T000001"].references == {}
    assert theIndex._itemIndex[cHandle]["T000001"].level == "H1"
    assert theIndex._itemIndex[cHandle]["T000001"].title == "Title One"
    assert theIndex._itemIndex[cHandle]["T000001"].charCount == 23
    assert theIndex._itemIndex[cHandle]["T000001"].wordCount == 4
    assert theIndex._itemIndex[cHandle]["T000001"].paraCount == 1
    assert theIndex._itemIndex[cHandle]["T000001"].synopsis == "Synopsis One."

    # Valid and Invalid References
    assert theIndex.scanText(
        sHandle,
        (
            "# Title One\n\n"
            "@pov: One\n\n"  # Valid
            "@char: Two\n\n"  # Invalid tag
            "@:\n\n"  # Invalid line
            "% synopsis: Synopsis One.\n\n"
            "Paragraph One.\n\n"))
    assert theIndex._itemIndex[sHandle]["T000001"].references == {
        "One": {"@pov"},
        "Two": {"@char"}
    }

    # Special Titles
    # ==============

    assert theIndex.scanText(tHandle, ("#! My Project\n\n"
                                       ">> By Jane Doe <<\n\n"))
    assert theIndex._itemIndex[cHandle]["T000001"].references == {}
    assert theIndex._itemIndex[tHandle]["T000001"].level == "H1"
    assert theIndex._itemIndex[tHandle]["T000001"].title == "My Project"
    assert theIndex._itemIndex[tHandle]["T000001"].charCount == 21
    assert theIndex._itemIndex[tHandle]["T000001"].wordCount == 5
    assert theIndex._itemIndex[tHandle]["T000001"].paraCount == 1
    assert theIndex._itemIndex[tHandle]["T000001"].synopsis == ""

    assert theIndex.scanText(tHandle,
                             ("##! Prologue\n\n"
                              "In the beginning there was time ...\n\n"))
    assert theIndex._itemIndex[cHandle]["T000001"].references == {}
    assert theIndex._itemIndex[tHandle]["T000001"].level == "H2"
    assert theIndex._itemIndex[tHandle]["T000001"].title == "Prologue"
    assert theIndex._itemIndex[tHandle]["T000001"].charCount == 43
    assert theIndex._itemIndex[tHandle]["T000001"].wordCount == 8
    assert theIndex._itemIndex[tHandle]["T000001"].paraCount == 1
    assert theIndex._itemIndex[tHandle]["T000001"].synopsis == ""

    # Page wo/Title
    # =============

    theProject.tree[pHandle]._layout = nwItemLayout.DOCUMENT
    assert theIndex.scanText(pHandle,
                             ("This is a page with some text on it.\n\n"))
    assert theIndex._itemIndex[pHandle]["T000000"].references == {}
    assert theIndex._itemIndex[pHandle]["T000000"].level == "H0"
    assert theIndex._itemIndex[pHandle]["T000000"].title == ""
    assert theIndex._itemIndex[pHandle]["T000000"].charCount == 36
    assert theIndex._itemIndex[pHandle]["T000000"].wordCount == 9
    assert theIndex._itemIndex[pHandle]["T000000"].paraCount == 1
    assert theIndex._itemIndex[pHandle]["T000000"].synopsis == ""

    theProject.tree[pHandle]._layout = nwItemLayout.NOTE
    assert theIndex.scanText(pHandle,
                             ("This is a page with some text on it.\n\n"))
    assert theIndex._itemIndex[pHandle]["T000000"].references == {}
    assert theIndex._itemIndex[pHandle]["T000000"].level == "H0"
    assert theIndex._itemIndex[pHandle]["T000000"].title == ""
    assert theIndex._itemIndex[pHandle]["T000000"].charCount == 36
    assert theIndex._itemIndex[pHandle]["T000000"].wordCount == 9
    assert theIndex._itemIndex[pHandle]["T000000"].paraCount == 1
    assert theIndex._itemIndex[pHandle]["T000000"].synopsis == ""

    assert theProject.closeProject() is True
Пример #10
0
def testCoreIndex_CheckThese(mockGUI, fncDir, mockRnd):
    """Test the tag checker function checkThese.
    """
    theProject = NWProject(mockGUI)
    buildTestProject(theProject, fncDir)
    theIndex = theProject.index

    nHandle = theProject.newFile("Hello", "0000000000010")
    cHandle = theProject.newFile("Jane", "0000000000012")
    nItem = theProject.tree[nHandle]
    cItem = theProject.tree[cHandle]

    assert theIndex.rootChangedSince("0000000000010", 0) is False
    assert theIndex.indexChangedSince(0) is False

    assert theIndex.scanText(cHandle, ("# Jane Smith\n"
                                       "@tag: Jane\n"
                                       "@tag:\n"
                                       "@:\n"))
    assert theIndex.scanText(
        nHandle,
        (
            "# Hello World!\n"
            "@pov: Jane\n"
            "@invalid: John\n"  # Checks for issue #688
        ))
    assert theIndex._tagsIndex.tagHandle("Jane") == cHandle
    assert theIndex._tagsIndex.tagHeading("Jane") == "T000001"
    assert theIndex._tagsIndex.tagClass("Jane") == "CHARACTER"
    assert theIndex.getNovelData(nHandle, "T000001").title == "Hello World!"
    assert theIndex.getReferences(nHandle, "T000001") == {
        "@char": [],
        "@custom": [],
        "@entity": [],
        "@focus": [],
        "@location": [],
        "@object": [],
        "@plot": [],
        "@pov": ["Jane"],
        "@time": []
    }

    assert theIndex.rootChangedSince("0000000000010", 0) is True
    assert theIndex.indexChangedSince(0) is True

    assert theIndex.getHandleHeaderLevel(cHandle) == "H1"
    assert theIndex.getHandleHeaderLevel(nHandle) == "H1"

    # Zero Items
    assert theIndex.checkThese([], cItem) == []

    # One Item
    assert theIndex.checkThese(["@tag"], cItem) == [True]
    assert theIndex.checkThese(["@who"], cItem) == [False]

    # Two Items
    assert theIndex.checkThese(["@tag", "Jane"], cItem) == [True, True]
    assert theIndex.checkThese(["@tag", "John"], cItem) == [True, True]
    assert theIndex.checkThese(["@tag", "Jane"], nItem) == [True, False]
    assert theIndex.checkThese(["@tag", "John"], nItem) == [True, True]
    assert theIndex.checkThese(["@pov", "John"], nItem) == [True, False]
    assert theIndex.checkThese(["@pov", "Jane"], nItem) == [True, True]
    assert theIndex.checkThese(["@ pov", "Jane"], nItem) == [False, False]
    assert theIndex.checkThese(["@what", "Jane"], nItem) == [False, False]

    # Three Items
    assert theIndex.checkThese(["@tag", "Jane", "John"],
                               cItem) == [True, True, False]
    assert theIndex.checkThese(["@who", "Jane", "John"],
                               cItem) == [False, False, False]
    assert theIndex.checkThese(["@pov", "Jane", "John"],
                               nItem) == [True, True, False]

    assert theProject.closeProject() is True