def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
    """Test the tag checker function checkThese.
    """
    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

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

    assert theIndex.scanText(cHandle, ("# Jane Smith\n" "@tag: Jane"))
    assert theIndex.scanText(nHandle, ("# Hello World!\n" "@pov: Jane"))
    assert theIndex.tagIndex == {"Jane": [2, cHandle, "CHARACTER", "T000001"]}
    assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"

    assert theIndex.checkThese([], cItem) == []
    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]

    assert theProject.closeProject()
Beispiel #2
0
def testIndexCheckThese(nwMinimal, nwDummy):
    """Test the tag checker function checkThese.
    """
    theProject = NWProject(nwDummy)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

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

    assert theIndex.scanText(cHandle, (
        "# Jane Smith\n"
        "@tag: Jane"
    ))
    assert theIndex.scanText(nHandle, (
        "# Hello World!\n"
        "@pov: Jane"
    ))
    assert str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle
    assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"

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

    assert theProject.closeProject()
Beispiel #3
0
def testIndexExtractData(nwMinimal, nwDummy):
    """Check the index data extraction functions.
    """
    theProject = NWProject(nwDummy)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

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

    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
    assert str(theIndex.getNovelStructure()) == "['%s:T000001']" % nHandle

    # 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 str(theRefs["@pov"]) == "['Jane']"
    assert str(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 str(theRefs) == "{'%s': 'T000001'}" % nHandle

    ##
    #  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.\n"
    ))
    # Whole document
    cC, wC, pC = theIndex.getCounts(nHandle)
    assert cC == 124
    assert wC == 24
    assert pC == 4

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

    # First part
    cC, wC, pC = theIndex.getCounts(nHandle, "T000011")
    assert cC == 62
    assert wC == 12
    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.\n"
    ))
    # Whole document
    cC, wC, pC = theIndex.getCounts(cHandle)
    assert cC == 124
    assert wC == 24
    assert pC == 4

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

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

    assert theProject.closeProject()
Beispiel #4
0
def testIndexScanText(nwMinimal, nwDummy):
    """Check the index data extraction functions.
    """
    theProject = NWProject(nwDummy)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

    theIndex = NWIndex(theProject, nwDummy)

    # 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 not theIndex.scanText(None, "Hello World!")
    assert not theIndex.scanText(dHandle, "Hello World!")
    assert not theIndex.scanText(xHandle, "Hello World!")

    xItem.setLayout(nwItemLayout.SCENE)
    xItem.setParent(None)
    assert not theIndex.scanText(xHandle, "Hello World!")

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

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

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

    # 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 str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle
    assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"

    # Check that title sections are indexed properly
    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 is counted as a word
        "Paragraph Five.\n\n"
    ))
    assert theIndex.refIndex[nHandle].get("T000000", None) is not None # Always there
    assert theIndex.refIndex[nHandle].get("T000001", None) is not None # Heading 1
    assert theIndex.refIndex[nHandle].get("T000002", None) is None
    assert theIndex.refIndex[nHandle].get("T000003", None) is None
    assert theIndex.refIndex[nHandle].get("T000004", None) is None
    assert theIndex.refIndex[nHandle].get("T000005", None) is None
    assert theIndex.refIndex[nHandle].get("T000006", None) is None
    assert theIndex.refIndex[nHandle].get("T000007", None) is not None # Heading 2
    assert theIndex.refIndex[nHandle].get("T000008", None) is None
    assert theIndex.refIndex[nHandle].get("T000009", None) is None
    assert theIndex.refIndex[nHandle].get("T000010", None) is None
    assert theIndex.refIndex[nHandle].get("T000011", None) is None
    assert theIndex.refIndex[nHandle].get("T000012", None) is None
    assert theIndex.refIndex[nHandle].get("T000013", None) is not None # Heading 3
    assert theIndex.refIndex[nHandle].get("T000014", None) is None
    assert theIndex.refIndex[nHandle].get("T000015", None) is None
    assert theIndex.refIndex[nHandle].get("T000016", None) is None
    assert theIndex.refIndex[nHandle].get("T000017", None) is None
    assert theIndex.refIndex[nHandle].get("T000018", None) is None
    assert theIndex.refIndex[nHandle].get("T000019", None) is not None # Heading 4
    assert theIndex.refIndex[nHandle].get("T000020", None) is None
    assert theIndex.refIndex[nHandle].get("T000021", None) is None
    assert theIndex.refIndex[nHandle].get("T000022", None) is None
    assert theIndex.refIndex[nHandle].get("T000023", None) is None
    assert theIndex.refIndex[nHandle].get("T000024", None) is None
    assert theIndex.refIndex[nHandle].get("T000025", None) is None
    assert theIndex.refIndex[nHandle].get("T000026", None) is None

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

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

    assert theIndex.novelIndex[nHandle]["T000001"]["layout"] == "SCENE"
    assert theIndex.novelIndex[nHandle]["T000007"]["layout"] == "SCENE"
    assert theIndex.novelIndex[nHandle]["T000013"]["layout"] == "SCENE"
    assert theIndex.novelIndex[nHandle]["T000019"]["layout"] == "SCENE"

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

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

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

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

    assert theIndex.scanText(cHandle, (
        "# Title One\n\n"
        "@tag: One\n\n"
        "% synopsis: Synopsis One.\n\n"
        "Paragraph One.\n\n"
    ))
    assert theIndex.refIndex[cHandle].get("T000000", None) is not None
    assert theIndex.refIndex[cHandle].get("T000001", None) is not None
    assert theIndex.refIndex[cHandle].get("T000002", None) is None
    assert theIndex.refIndex[cHandle].get("T000003", None) is None
    assert theIndex.refIndex[cHandle].get("T000004", None) is None
    assert theIndex.refIndex[cHandle].get("T000005", None) is None
    assert theIndex.refIndex[cHandle].get("T000006", None) is None
    assert theIndex.refIndex[cHandle].get("T000007", None) is None

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

    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 str(theIndex.refIndex[sHandle]["T000001"]["tags"]) == (
        "[[3, '@pov', 'One'], [5, '@char', 'Two']]"
    )

    assert theProject.closeProject()
Beispiel #5
0
def testIndexBuildCheck(monkeypatch, nwLipsum, nwDummy, nwTempProj, nwRef):
    """Test core functionality of scaning, saving, loading and checking
    the index cache file.
    """
    projFile = os.path.join(nwLipsum, "meta", "tagsIndex.json")
    testFile = os.path.join(nwTempProj, "1_tagsIndex.json")
    refFile  = os.path.join(nwRef, "proj", "1_tagsIndex.json")

    theProject = NWProject(nwDummy)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwLipsum)

    monkeypatch.setattr("nw.core.index.time", lambda: 123.4)

    theIndex = NWIndex(theProject, nwDummy)
    notIndexable = {
        "b3643d0f92e32": False, # Novel ROOT
        "45e6b01ca35c1": False, # Chapter One FOLDER
        "6bd935d2490cd": False, # Chapter Two FOLDER
        "67a8707f2f249": False, # Character ROOT
        "6c6afb1247750": False, # Plot ROOT
        "60bdf227455cc": False, # World ROOT
    }
    for tItem in theProject.projTree:
        assert theIndex.reIndexHandle(tItem.itemHandle) is notIndexable.get(tItem.itemHandle, True)

    assert not theIndex.reIndexHandle(None)

    # Dummy exception function
    def doPanic(*arg, **kwargs):
        raise Exception

    # Make the save fail
    monkeypatch.setattr(json, "dump", doPanic)
    assert not theIndex.saveIndex()

    # Make the save pass
    monkeypatch.undo()
    assert theIndex.saveIndex()

    # Take a copy of the index
    tagIndex = str(theIndex.tagIndex)
    refIndex = str(theIndex.refIndex)
    novelIndex = str(theIndex.novelIndex)
    noteIndex = str(theIndex.noteIndex)
    textCounts = str(theIndex.textCounts)

    # Delete a handle
    assert theIndex.tagIndex.get("Bod", None) is not None
    assert theIndex.refIndex.get("4c4f28287af27", None) is not None
    assert theIndex.noteIndex.get("4c4f28287af27", None) is not None
    assert theIndex.textCounts.get("4c4f28287af27", None) is not None
    theIndex.deleteHandle("4c4f28287af27")
    assert theIndex.tagIndex.get("Bod", None) is None
    assert theIndex.refIndex.get("4c4f28287af27", None) is None
    assert theIndex.noteIndex.get("4c4f28287af27", None) is None
    assert theIndex.textCounts.get("4c4f28287af27", None) is None

    # Clear the index
    theIndex.clearIndex()
    assert not theIndex.tagIndex
    assert not theIndex.refIndex
    assert not theIndex.novelIndex
    assert not theIndex.noteIndex
    assert not theIndex.textCounts

    # Make the load fail
    monkeypatch.setattr(json, "load", doPanic)
    assert not theIndex.loadIndex()

    # Make the load pass
    monkeypatch.undo()
    assert theIndex.loadIndex()

    assert str(theIndex.tagIndex) == tagIndex
    assert str(theIndex.refIndex) == refIndex
    assert str(theIndex.novelIndex) == novelIndex
    assert str(theIndex.noteIndex) == noteIndex
    assert str(theIndex.textCounts) == textCounts

    # Break the index and check that we notice
    assert not theIndex.indexBroken
    theIndex.tagIndex["Bod"].append("Stuff") # No longer len() == 4
    theIndex.checkIndex()
    assert theIndex.indexBroken

    assert theIndex.loadIndex()
    assert not theIndex.indexBroken
    theIndex.refIndex["fb609cd8319dc"]["T000001"]["tags"].append("Stuff") # No longer len() == 3
    theIndex.checkIndex()
    assert theIndex.indexBroken

    assert theIndex.loadIndex()
    assert not theIndex.indexBroken
    theIndex.novelIndex["7a992350f3eb6"]["T000001"]["Stuff"] = "" # No longer len(keys()) == 8
    theIndex.checkIndex()
    assert theIndex.indexBroken

    assert theIndex.loadIndex()
    assert not theIndex.indexBroken
    theIndex.noteIndex["4c4f28287af27"]["T000001"]["Stuff"] = "" # No longer len(keys()) == 8
    theIndex.checkIndex()
    assert theIndex.indexBroken

    assert theIndex.loadIndex()
    assert not theIndex.indexBroken
    theIndex.textCounts["7a992350f3eb6"].append("Stuff") # No longer len() == 3
    theIndex.checkIndex()
    assert theIndex.indexBroken

    # Make the try/except trigger as well
    assert theIndex.loadIndex()
    assert not theIndex.indexBroken
    theIndex.refIndex["fb609cd8319dc"]["T000001"] = {"tagssss": []} # Wrong key name
    theIndex.checkIndex()
    assert theIndex.indexBroken

    # Finalise
    assert theProject.closeProject()

    copyfile(projFile, testFile)
    assert cmpFiles(testFile, refFile)
Beispiel #6
0
def testIndexScanThis(nwMinimal, nwDummy):
    """Test the tag scanner function scanThis.
    """
    theProject = NWProject(nwDummy)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

    theIndex = NWIndex(theProject, nwDummy)

    isValid, theBits, thePos = theIndex.scanThis("tag: this, and this")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@:")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis(" @a: b")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@a:")
    assert isValid
    assert str(theBits) == "['@a']"
    assert str(thePos)  == "[0]"

    isValid, theBits, thePos = theIndex.scanThis("@a:b")
    assert isValid
    assert str(theBits) == "['@a', 'b']"
    assert str(thePos)  == "[0, 3]"

    isValid, theBits, thePos = theIndex.scanThis("@a:b,c,d")
    assert isValid
    assert str(theBits) == "['@a', 'b', 'c', 'd']"
    assert str(thePos)  == "[0, 3, 5, 7]"

    isValid, theBits, thePos = theIndex.scanThis("@a : b , c , d")
    assert isValid
    assert str(theBits) == "['@a', 'b', 'c', 'd']"
    assert str(thePos)  == "[0, 5, 9, 13]"

    isValid, theBits, thePos = theIndex.scanThis("@tag: this, and this")
    assert isValid
    assert str(theBits) == "['@tag', 'this', 'and this']"
    assert str(thePos)  == "[0, 6, 12]"

    assert theProject.closeProject()
def testCoreIndex_CheckNovelNoteIndex(dummyGUI):
    """Test the novel and note index checkers.
    """
    theProject = NWProject(dummyGUI)
    theIndex = NWIndex(theProject, dummyGUI)

    # Valid Index
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    theIndex._noteIndex = theIndex._novelIndex.copy()
    assert theIndex._checkNovelNoteIndex("novelIndex") is None
    assert theIndex._checkNovelNoteIndex("noteIndex") is None
    with pytest.raises(IndexError):
        theIndex._checkNovelNoteIndex("notAnIndex")

    # Invalid Handle
    theIndex._novelIndex = {
        "H3b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Invalid Title
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "INVALID": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Length
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868,
                "stuff": None
            }
        }
    }
    with pytest.raises(IndexError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing Keys
    # ============

    # Missing 'level'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "stuff": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'title'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "stuff": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'layout'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "stuff": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'synopsis'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "stuff": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'cCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "stuff": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'wCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "stuff": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'pCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "stuff": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Missing 'updated'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "stuff": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Types
    # ===========

    # Wrong Type for 'level'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "XX",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'title'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": 12345678,
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'layout'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "INVALID",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'synopsis'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": 123456,
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'cCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": "72",
                "wCount": 15,
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'wCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": "15",
                "pCount": 2,
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'pCount'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": "2",
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")

    # Wrong Type for 'updated'
    theIndex._novelIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "TITLE",
                "synopsis": "text",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "updated": "1611922868"
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkNovelNoteIndex("novelIndex")
def testCoreIndex_ScanThis(nwMinimal, dummyGUI):
    """Test the tag scanner function scanThis.
    """
    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

    theIndex = NWIndex(theProject, dummyGUI)

    isValid, theBits, thePos = theIndex.scanThis("tag: this, and this")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@:")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis(" @a: b")
    assert not isValid

    isValid, theBits, thePos = theIndex.scanThis("@a:")
    assert isValid
    assert theBits == ["@a"]
    assert thePos == [0]

    isValid, theBits, thePos = theIndex.scanThis("@a:b")
    assert isValid
    assert theBits == ["@a", "b"]
    assert thePos == [0, 3]

    isValid, theBits, thePos = theIndex.scanThis("@a:b,c,d")
    assert isValid
    assert theBits == ["@a", "b", "c", "d"]
    assert thePos == [0, 3, 5, 7]

    isValid, theBits, thePos = theIndex.scanThis("@a : b , c , d")
    assert isValid
    assert theBits == ["@a", "b", "c", "d"]
    assert thePos == [0, 5, 9, 13]

    isValid, theBits, thePos = theIndex.scanThis("@tag: this, and this")
    assert isValid
    assert theBits == ["@tag", "this", "and this"]
    assert thePos == [0, 6, 12]

    assert theProject.closeProject()
def testCoreIndex_CheckTagIndex(dummyGUI):
    """Test the tag index checker.
    """
    theProject = NWProject(dummyGUI)
    theIndex = NWIndex(theProject, dummyGUI)

    # Valid Index
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": [3, "bb2c23b3c42cc", "CHARACTER", "T000001"],
    }
    assert theIndex._checkTagIndex() is None

    # Wrong Key Type
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        123456: [3, "bb2c23b3c42cc", "CHARACTER", "T000001"],
    }
    with pytest.raises(KeyError):
        theIndex._checkTagIndex()

    # Wrong Length
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": [3, "bb2c23b3c42cc", "CHARACTER", "T000001", "Stuff"],
    }
    with pytest.raises(IndexError):
        theIndex._checkTagIndex()

    # Wrong Type of Entry 0
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": ["3", "bb2c23b3c42cc", "CHARACTER", "T000001"],
    }
    with pytest.raises(ValueError):
        theIndex._checkTagIndex()

    # Wrong Type of Entry 1
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": [3, 0xbb2c23b3c42cc, "CHARACTER", "T000001"],
    }
    with pytest.raises(ValueError):
        theIndex._checkTagIndex()

    # Wrong Type of Entry 2
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": [3, "bb2c23b3c42cc", "INVALID_CLASS", "T000001"],
    }
    with pytest.raises(ValueError):
        theIndex._checkTagIndex()

    # Wrong Type of Entry 3
    theIndex._tagIndex = {
        "John": [3, "14298de4d9524", "CHARACTER", "T000001"],
        "Jane": [3, "bb2c23b3c42cc", "CHARACTER", "INVALID"],
    }
    with pytest.raises(ValueError):
        theIndex._checkTagIndex()
Beispiel #10
0
def testCoreIndex_CheckRefIndex(dummyGUI):
    """Test the reference index checker.
    """
    theProject = NWProject(dummyGUI)
    theIndex = NWIndex(theProject, dummyGUI)

    # Valid Index
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"], [4, "@location", "Earth"]],
                "updated": 1611922868
            }
        }
    }
    assert theIndex._checkRefIndex() is None

    # Invalid Handle
    theIndex._refIndex = {
        "Ha2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"], [4, "@location", "Earth"]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkRefIndex()

    # Invalid Title
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "INVALID": {
                "tags": [[3, "@pov", "Jane"], [4, "@location", "Earth"]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkRefIndex()

    # Missing 'tags'
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkRefIndex()

    # Wrong Length of 'tags'
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"],
                         [4, "@location", "Earth", "Stuff"]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(IndexError):
        theIndex._checkRefIndex()

    # Wrong Type of 'tags' Entry 0
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"], ["4", "@location", "Earth"]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkRefIndex()

    # Wrong Type of 'tags' Entry 1
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"], [4, "@stuff", "Earth"]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkRefIndex()

    # Wrong Type of 'tags' Entry 1
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [[3, "@pov", "Jane"], [4, "@location", 123456]],
                "updated": 1611922868
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkRefIndex()

    # Missing 'updated'
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": []
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkRefIndex()

    # Wrong Type of 'updated' Entry 1
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": {
                "tags": [],
                "updated": 1611922868
            },
            "T000001": {
                "tags": [],
                "updated": "1611922868"
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkRefIndex()
Beispiel #11
0
def testCoreIndex_ExtractData(nwMinimal, dummyGUI):
    """Check the index data extraction functions.
    """
    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

    theIndex = NWIndex(theProject, dummyGUI)
    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.CHAPTER
    theProject.projTree[sHandle].itemLayout == nwItemLayout.SCENE
    theProject.projTree[tHandle].itemLayout == nwItemLayout.SCENE

    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!")
    ]
Beispiel #12
0
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, dummyGUI, outDir, refDir):
    """Test core functionality of scaning, saving, loading and checking
    the index cache file.
    """
    projFile = os.path.join(nwLipsum, "meta", "tagsIndex.json")
    testFile = os.path.join(outDir, "coreIndex_LoadSave_tagsIndex.json")
    compFile = os.path.join(refDir, "coreIndex_LoadSave_tagsIndex.json")

    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwLipsum)

    monkeypatch.setattr("nw.core.index.time", lambda: 123.4)

    theIndex = NWIndex(theProject, dummyGUI)
    notIndexable = {
        "b3643d0f92e32": False,  # Novel ROOT
        "45e6b01ca35c1": False,  # Chapter One FOLDER
        "6bd935d2490cd": False,  # Chapter Two FOLDER
        "67a8707f2f249": False,  # Character ROOT
        "6c6afb1247750": False,  # Plot ROOT
        "60bdf227455cc": False,  # World ROOT
    }
    for tItem in theProject.projTree:
        assert theIndex.reIndexHandle(tItem.itemHandle) is notIndexable.get(
            tItem.itemHandle, True)

    assert not theIndex.reIndexHandle(None)

    # Make the save fail
    with monkeypatch.context() as mp:
        mp.setattr(json, "dump", causeException)
        assert not theIndex.saveIndex()

    # Make the save pass
    assert theIndex.saveIndex()

    # Take a copy of the index
    tagIndex = str(theIndex._tagIndex)
    refIndex = str(theIndex._refIndex)
    novelIndex = str(theIndex._novelIndex)
    noteIndex = str(theIndex._noteIndex)
    textCounts = str(theIndex._textCounts)

    # Delete a handle
    assert theIndex._tagIndex.get("Bod", None) is not None
    assert theIndex._refIndex.get("4c4f28287af27", None) is not None
    assert theIndex._noteIndex.get("4c4f28287af27", None) is not None
    assert theIndex._textCounts.get("4c4f28287af27", None) is not None
    theIndex.deleteHandle("4c4f28287af27")
    assert theIndex._tagIndex.get("Bod", None) is None
    assert theIndex._refIndex.get("4c4f28287af27", None) is None
    assert theIndex._noteIndex.get("4c4f28287af27", None) is None
    assert theIndex._textCounts.get("4c4f28287af27", None) is None

    # Clear the index
    theIndex.clearIndex()
    assert not theIndex._tagIndex
    assert not theIndex._refIndex
    assert not theIndex._novelIndex
    assert not theIndex._noteIndex
    assert not theIndex._textCounts

    # Make the load fail
    with monkeypatch.context() as mp:
        mp.setattr(json, "load", causeException)
        assert not theIndex.loadIndex()

    # Make the load pass
    assert theIndex.loadIndex()

    assert str(theIndex._tagIndex) == tagIndex
    assert str(theIndex._refIndex) == refIndex
    assert str(theIndex._novelIndex) == novelIndex
    assert str(theIndex._noteIndex) == noteIndex
    assert str(theIndex._textCounts) == textCounts

    # Break the index and check that we notice
    assert not theIndex.indexBroken
    theIndex._tagIndex["Bod"].append("Stuff")
    theIndex.checkIndex()
    assert theIndex.indexBroken

    # Finalise
    assert theProject.closeProject()

    copyfile(projFile, testFile)
    assert cmpFiles(testFile, compFile)
Beispiel #13
0
def testCoreIndex_ScanText(nwMinimal, dummyGUI):
    """Check the index text scanner.
    """
    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

    theIndex = NWIndex(theProject, dummyGUI)

    # 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 not theIndex.scanText(None, "Hello World!")
    assert not theIndex.scanText(dHandle, "Hello World!")
    assert not theIndex.scanText(xHandle, "Hello World!")

    xItem.setLayout(nwItemLayout.SCENE)
    xItem.setParent(None)
    assert not theIndex.scanText(xHandle, "Hello World!")

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

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

    # Make some usable items
    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")

    # 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!"

    # Check that title sections are indexed properly
    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._refIndex[nHandle].get("T000000",
                                           None) is not None  # Always there
    assert theIndex._refIndex[nHandle].get("T000001",
                                           None) is not None  # Heading 1
    assert theIndex._refIndex[nHandle].get("T000002", None) is None
    assert theIndex._refIndex[nHandle].get("T000003", None) is None
    assert theIndex._refIndex[nHandle].get("T000004", None) is None
    assert theIndex._refIndex[nHandle].get("T000005", None) is None
    assert theIndex._refIndex[nHandle].get("T000006", None) is None
    assert theIndex._refIndex[nHandle].get("T000007",
                                           None) is not None  # Heading 2
    assert theIndex._refIndex[nHandle].get("T000008", None) is None
    assert theIndex._refIndex[nHandle].get("T000009", None) is None
    assert theIndex._refIndex[nHandle].get("T000010", None) is None
    assert theIndex._refIndex[nHandle].get("T000011", None) is None
    assert theIndex._refIndex[nHandle].get("T000012", None) is None
    assert theIndex._refIndex[nHandle].get("T000013",
                                           None) is not None  # Heading 3
    assert theIndex._refIndex[nHandle].get("T000014", None) is None
    assert theIndex._refIndex[nHandle].get("T000015", None) is None
    assert theIndex._refIndex[nHandle].get("T000016", None) is None
    assert theIndex._refIndex[nHandle].get("T000017", None) is None
    assert theIndex._refIndex[nHandle].get("T000018", None) is None
    assert theIndex._refIndex[nHandle].get("T000019",
                                           None) is not None  # Heading 4
    assert theIndex._refIndex[nHandle].get("T000020", None) is None
    assert theIndex._refIndex[nHandle].get("T000021", None) is None
    assert theIndex._refIndex[nHandle].get("T000022", None) is None
    assert theIndex._refIndex[nHandle].get("T000023", None) is None
    assert theIndex._refIndex[nHandle].get("T000024", None) is None
    assert theIndex._refIndex[nHandle].get("T000025", None) is None
    assert theIndex._refIndex[nHandle].get("T000026", None) is None

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

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

    assert theIndex._novelIndex[nHandle]["T000001"]["layout"] == "SCENE"
    assert theIndex._novelIndex[nHandle]["T000007"]["layout"] == "SCENE"
    assert theIndex._novelIndex[nHandle]["T000013"]["layout"] == "SCENE"
    assert theIndex._novelIndex[nHandle]["T000019"]["layout"] == "SCENE"

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

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

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

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

    assert theIndex.scanText(cHandle, ("# Title One\n\n"
                                       "@tag: One\n\n"
                                       "% synopsis: Synopsis One.\n\n"
                                       "Paragraph One.\n\n"))
    assert theIndex._refIndex[cHandle].get("T000000", None) is not None
    assert theIndex._refIndex[cHandle].get("T000001", None) is not None
    assert theIndex._refIndex[cHandle].get("T000002", None) is None
    assert theIndex._refIndex[cHandle].get("T000003", None) is None
    assert theIndex._refIndex[cHandle].get("T000004", None) is None
    assert theIndex._refIndex[cHandle].get("T000005", None) is None
    assert theIndex._refIndex[cHandle].get("T000006", None) is None
    assert theIndex._refIndex[cHandle].get("T000007", None) is None

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

    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"]["tags"] == ([[
        3, "@pov", "One"
    ], [5, "@char", "Two"]])

    # Page wo/Title
    theProject.projTree[pHandle].itemLayout = nwItemLayout.PAGE
    assert theIndex.scanText(pHandle,
                             ("This is a page with some text on it.\n\n"))
    assert theIndex._novelIndex[pHandle]["T000000"]["level"] == "H0"
    assert theIndex._novelIndex[pHandle]["T000000"]["title"] == "Untitled Page"
    assert theIndex._novelIndex[pHandle]["T000000"]["layout"] == "PAGE"
    assert theIndex._novelIndex[pHandle]["T000000"]["synopsis"] == ""
    assert theIndex._novelIndex[pHandle]["T000000"]["cCount"] == 36
    assert theIndex._novelIndex[pHandle]["T000000"]["wCount"] == 9
    assert theIndex._novelIndex[pHandle]["T000000"]["pCount"] == 1
    assert pHandle not in theIndex._noteIndex

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

    assert theProject.closeProject()
Beispiel #14
0
def testCoreIndex_CheckThese(nwMinimal, dummyGUI):
    """Test the tag checker function checkThese.
    """
    theProject = NWProject(dummyGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal)

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

    assert not theIndex.novelChangedSince(0)
    assert not theIndex.notesChangedSince(0)
    assert not theIndex.indexChangedSince(0)

    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)
    assert theIndex.notesChangedSince(0)
    assert theIndex.indexChangedSince(0)

    assert theIndex.checkThese([], cItem) == []
    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]

    assert theProject.closeProject()
Beispiel #15
0
def testCoreIndex_CheckTextCounts(dummyGUI):
    """Test the text counts checker.
    """
    theProject = NWProject(dummyGUI)
    theIndex = NWIndex(theProject, dummyGUI)

    # Valid Index
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "974e400180a99": [210, 40, 2],
    }
    assert theIndex._checkTextCounts() is None

    # Invalid Handle
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "h74e400180a99": [210, 40, 2],
    }
    with pytest.raises(KeyError):
        theIndex._checkTextCounts()

    # Wrong Length
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "974e400180a99": [210, 40, 2, 8],
    }
    with pytest.raises(IndexError):
        theIndex._checkTextCounts()

    # Type of Entry 0
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "974e400180a99": ["210", 40, 2],
    }
    with pytest.raises(ValueError):
        theIndex._checkTextCounts()

    # Type of Entry 1
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "974e400180a99": [210, "40", 2],
    }
    with pytest.raises(ValueError):
        theIndex._checkTextCounts()

    # Type of Entry 2
    theIndex._textCounts = {
        "53b69b83cdafc": [72, 15, 2],
        "974e400180a99": [210, 40, "2"],
    }
    with pytest.raises(ValueError):
        theIndex._checkTextCounts()