コード例 #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 testCoreTree_MakeHandles(mockGUI):
    """Test generating item handles.
    """
    random.seed(42)
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    handles = [
        "1c803a3b1799d", "bdd6406671ad1", "3eb1346685257", "23b8c392456de"
    ]

    random.seed(42)
    tHandle = theTree._makeHandle()
    assert tHandle == handles[0]
    theTree._projTree[handles[0]] = None

    # Add the next in line to the project to force duplicate
    theTree._projTree[handles[1]] = None
    tHandle = theTree._makeHandle()
    assert tHandle == handles[2]
    theTree._projTree[handles[2]] = None

    # Reset the seed to force collissions, which should still end up
    # returning the next handle in the sequence
    random.seed(42)
    tHandle = theTree._makeHandle()
    assert tHandle == handles[3]
コード例 #3
0
def testCoreIndex_CheckTagIndex(mockGUI):
    """Test the tag index checker.
    """
    theProject = NWProject(mockGUI)
    theIndex = NWIndex(theProject)

    # 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()
コード例 #4
0
def testCoreTree_Reorder(mockGUI, mockItems):
    """Test changing tree order.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    aHandle = []
    for tHandle, pHandle, nwItem in mockItems:
        aHandle.append(tHandle)
        theTree.append(tHandle, pHandle, nwItem)

    assert len(theTree) == len(mockItems)

    bHandle = aHandle.copy()
    bHandle[2], bHandle[3] = bHandle[3], bHandle[2]
    assert aHandle != bHandle

    assert theTree.handles() == aHandle
    theTree.setOrder(bHandle)
    assert theTree.handles() == bHandle

    theTree.setOrder(bHandle + ["stuff"])
    assert theTree.handles() == bHandle

    theTree._treeOrder.append("stuff")
    theTree.setOrder(bHandle)
    assert theTree.handles() == bHandle
コード例 #5
0
def testCoreProject_NewSampleB(monkeypatch, fncDir, tmpConf, mockGUI, tmpDir):
    """Check that we can create a new project can be created from the
    provided sample project folder.
    """
    projData = {
        "projName": "Test Sample",
        "projTitle": "Test Novel",
        "projAuthors": "Jane Doe\nJohn Doh\n",
        "projPath": fncDir,
        "popSample": True,
        "popMinimal": False,
        "popCustom": False,
    }
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)

    # Make sure we do not pick up the novelwriter/assets/sample.zip file
    tmpConf.assetPath = tmpDir

    # Set a fake project file name
    monkeypatch.setattr(nwFiles, "PROJ_FILE", "nothing.nwx")
    assert not theProject.newProject(projData)

    monkeypatch.setattr(nwFiles, "PROJ_FILE", "nwProject.nwx")
    assert theProject.newProject(projData) is True
    assert theProject.openProject(fncDir) is True
    assert theProject.projName == "Sample Project"
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True

    # Misdirect the appRoot path so neither is possible
    tmpConf.appRoot = tmpDir
    assert not theProject.newProject(projData)
コード例 #6
0
def testCoreIndex_CheckFileMeta(mockGUI):
    """Test the file meta checker.
    """
    theProject = NWProject(mockGUI)
    theIndex = NWIndex(theProject)

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

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

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

    # Content of Entry 0
    theIndex._fileMeta = {
        "53b69b83cdafc": ["H0", 72, 15, 2],
        "974e400180a99": ["XXX", 210, 40, 2],
    }
    with pytest.raises(ValueError):
        theIndex._checkFileMeta()

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

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

    # Type of Entry 3
    theIndex._fileMeta = {
        "53b69b83cdafc": ["H0", 72, 15, 2],
        "974e400180a99": ["H0", 210, 40, "2"],
    }
    with pytest.raises(ValueError):
        theIndex._checkFileMeta()
コード例 #7
0
def testCoreTree_Methods(mockGUI, mockItems):
    """Test various class methods.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    for tHandle, pHandle, nwItem in mockItems:
        theTree.append(tHandle, pHandle, nwItem)

    assert len(theTree) == len(mockItems)

    # Chech type
    assert theTree.checkType("blabla", nwItemType.FILE) is False
    assert theTree.checkType("b000000000001", nwItemType.FILE) is False
    assert theTree.checkType("c000000000001", nwItemType.FILE) is True

    # Root item lookup
    theTree._treeRoots.append("stuff")
    assert theTree.findRoot(nwItemClass.WORLD) is None
    assert theTree.findRoot(nwItemClass.NOVEL) == "a000000000001"
    assert theTree.findRoot(nwItemClass.CHARACTER) == "a000000000004"

    # Check for root uniqueness
    assert theTree.checkRootUnique(nwItemClass.CUSTOM)
    assert theTree.checkRootUnique(nwItemClass.WORLD)
    assert not theTree.checkRootUnique(nwItemClass.NOVEL)
    assert not theTree.checkRootUnique(nwItemClass.CHARACTER)

    # Find root item of child item
    assert theTree.getRootItem("b000000000001").itemHandle == "a000000000001"
    assert theTree.getRootItem("c000000000001").itemHandle == "a000000000001"
    assert theTree.getRootItem("c000000000002").itemHandle == "a000000000001"
    assert theTree.getRootItem("stuff") is None

    # Get item path
    assert theTree.getItemPath("stuff") == []
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001", "a000000000001"
    ]

    # Break the folder parent handle
    theTree["b000000000001"]._parent = "stuff"
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001"
    ]

    theTree["b000000000001"]._parent = "a000000000001"
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001", "a000000000001"
    ]

    # Change file layout
    assert theTree.setFileItemLayout("stuff", nwItemLayout.DOCUMENT) is False
    assert theTree.setFileItemLayout("b000000000001",
                                     nwItemLayout.DOCUMENT) is False
    assert theTree.setFileItemLayout("c000000000001", "stuff") is False
    assert theTree.setFileItemLayout("c000000000001",
                                     nwItemLayout.NOTE) is True
    assert theTree["c000000000001"].itemLayout == nwItemLayout.NOTE
コード例 #8
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
コード例 #9
0
def testCoreProject_LockFile(monkeypatch, fncDir, mockGUI):
    """Test lock file functions for the project folder.
    """
    theProject = NWProject(mockGUI)

    lockFile = os.path.join(fncDir, nwFiles.PROJ_LOCK)

    # No project
    assert theProject._writeLockFile() is False
    assert theProject._readLockFile() == ["ERROR"]
    assert theProject._clearLockFile() is False

    theProject.projPath = fncDir
    theProject.mainConf.hostName = "TestHost"
    theProject.mainConf.osType = "TestOS"
    theProject.mainConf.kernelVer = "1.0"

    # Block open
    with monkeypatch.context() as mp:
        mp.setattr("builtins.open", causeOSError)
        assert theProject._writeLockFile() is False

    # Write lock file
    with monkeypatch.context() as mp:
        mp.setattr("novelwriter.core.project.time", lambda: 123.4)
        assert theProject._writeLockFile() is True
    assert readFile(lockFile) == "TestHost\nTestOS\n1.0\n123\n"

    # Block open
    with monkeypatch.context() as mp:
        mp.setattr("builtins.open", causeOSError)
        assert theProject._readLockFile() == ["ERROR"]

    # Read lock file
    assert theProject._readLockFile() == ["TestHost", "TestOS", "1.0", "123"]

    # Block unlink
    with monkeypatch.context() as mp:
        mp.setattr("os.unlink", causeOSError)
        assert os.path.isfile(lockFile)
        assert theProject._clearLockFile() is False
        assert os.path.isfile(lockFile)

    # Clear file
    assert os.path.isfile(lockFile)
    assert theProject._clearLockFile() is True
    assert not os.path.isfile(lockFile)

    # Read again, no file
    assert theProject._readLockFile() == []

    # Read an invalid lock file
    writeFile(lockFile, "A\nB")
    assert theProject._readLockFile() == ["ERROR"]
    assert theProject._clearLockFile() is True
コード例 #10
0
def testCoreTree_XMLPackUnpack(mockGUI, mockItems):
    """Test packing and unpacking the tree to and from XML.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    for tHandle, pHandle, nwItem in mockItems:
        theTree.append(tHandle, pHandle, nwItem)
        theTree.updateItemData(tHandle)

    assert len(theTree) == len(mockItems)

    nwXML = etree.Element("novelWriterXML")
    theTree.packXML(nwXML)
    assert etree.tostring(nwXML, pretty_print=False, encoding="utf-8") == (
        b'<novelWriterXML>'
        b'<content count="8">'
        b'<item handle="a000000000001" parent="None" root="a000000000001" order="0" type="ROOT" '
        b'class="NOVEL"><meta expanded="True"/><name status="s000000" '
        b'import="i000004">Novel</name></item>'
        b'<item handle="b000000000001" parent="a000000000001" root="a000000000001" order="0" '
        b'type="FOLDER" class="NOVEL"><meta expanded="True"/><name status="s000000" '
        b'import="i000004">Act One</name></item>'
        b'<item handle="c000000000001" parent="b000000000001" root="a000000000001" order="0" '
        b'type="FILE" class="NOVEL" layout="DOCUMENT"><meta expanded="False" charCount="300" '
        b'wordCount="50" paraCount="2" cursorPos="0"/><name status="s000000" import="i000004" '
        b'exported="True">Chapter One</name></item>'
        b'<item handle="c000000000002" parent="b000000000001" root="a000000000001" order="0" '
        b'type="FILE" class="NOVEL" layout="DOCUMENT"><meta expanded="False" charCount="3000" '
        b'wordCount="500" paraCount="20" cursorPos="0"/><name status="s000000" import="i000004" '
        b'exported="True">Scene One</name></item>'
        b'<item handle="a000000000002" parent="None" root="a000000000002" order="0" type="ROOT" '
        b'class="ARCHIVE"><meta expanded="False"/><name status="s000000" '
        b'import="i000004">Outtakes</name></item>'
        b'<item handle="a000000000003" parent="None" root="a000000000003" order="0" type="ROOT" '
        b'class="TRASH"><meta expanded="False"/><name status="s000000" '
        b'import="i000004">Trash</name></item>'
        b'<item handle="a000000000004" parent="None" root="a000000000004" order="0" type="ROOT" '
        b'class="CHARACTER"><meta expanded="True"/><name status="s000000" '
        b'import="i000004">Characters</name></item>'
        b'<item handle="b000000000002" parent="a000000000004" root="a000000000004" order="0" '
        b'type="FILE" class="CHARACTER" layout="NOTE"><meta expanded="False" charCount="2000" '
        b'wordCount="400" paraCount="16" cursorPos="0"/><name status="s000000" import="i000004" '
        b'exported="True">Jane Doe</name></item>'
        b'</content>'
        b'</novelWriterXML>')

    theTree.clear()
    assert len(theTree) == 0
    assert not theTree.unpackXML(nwXML)
    assert theTree.unpackXML(nwXML[0])
    assert len(theTree) == len(mockItems)
コード例 #11
0
def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir):
    """Test saving a project.
    """
    theProject = NWProject(mockGUI)
    testFile = os.path.join(nwMinimal, "nwProject.nwx")
    backFile = os.path.join(nwMinimal, "nwProject.bak")
    compFile = os.path.join(refDir, os.path.pardir, "minimal", "nwProject.nwx")

    # Nothing to save
    assert theProject.saveProject() is False

    # Open test project
    assert theProject.openProject(nwMinimal)

    # Fail on folder structure check
    with monkeypatch.context() as mp:
        mp.setattr("os.path.isdir", lambda *a: False)
        assert theProject.saveProject() is False

    # Fail on open file
    with monkeypatch.context() as mp:
        mp.setattr("builtins.open", causeOSError)
        assert theProject.saveProject() is False

    # Fail on creating .bak file
    with monkeypatch.context() as mp:
        mp.setattr("os.replace", causeOSError)
        assert theProject.saveProject() is False
        assert os.path.isfile(backFile) is False

    # Successful save
    saveCount = theProject.saveCount
    autoCount = theProject.autoCount
    assert theProject.saveProject() is True
    assert theProject.saveCount == saveCount + 1
    assert theProject.autoCount == autoCount
    assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9])

    # Check that a second save creates a .bak file
    assert os.path.isfile(backFile) is True

    # Successful autosave
    saveCount = theProject.saveCount
    autoCount = theProject.autoCount
    assert theProject.saveProject(autoSave=True) is True
    assert theProject.saveCount == saveCount
    assert theProject.autoCount == autoCount + 1
    assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9])

    # Close test project
    assert theProject.closeProject()
コード例 #12
0
def testCoreTree_Stats(mockGUI, mockItems):
    """Test project stats methods.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    for tHandle, pHandle, nwItem in mockItems:
        theTree.append(tHandle, pHandle, nwItem)

    assert len(theTree) == len(mockItems)
    theTree._treeOrder.append("stuff")

    # Count Words
    novelWords, noteWords = theTree.sumWords()
    assert novelWords == 550
    assert noteWords == 400
コード例 #13
0
def testCoreIndex_ScanThis(nwMinimal, mockGUI):
    """Test the tag scanner function scanThis.
    """
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwMinimal) is True

    theIndex = NWIndex(theProject)

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

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

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

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

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

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

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

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

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

    assert theProject.closeProject() is True
コード例 #14
0
def testCoreProject_NewCustomA(fncDir, outDir, refDir, mockGUI):
    """Create a new project from a project wizard dictionary.
    Custom type with chapters and scenes.
    """
    projFile = os.path.join(fncDir, "nwProject.nwx")
    testFile = os.path.join(outDir, "coreProject_NewCustomA_nwProject.nwx")
    compFile = os.path.join(refDir, "coreProject_NewCustomA_nwProject.nwx")

    projData = {
        "projName":
        "Test Custom",
        "projTitle":
        "Test Novel",
        "projAuthors":
        "Jane Doe\nJohn Doh\n",
        "projPath":
        fncDir,
        "popSample":
        False,
        "popMinimal":
        False,
        "popCustom":
        True,
        "addRoots": [
            nwItemClass.PLOT,
            nwItemClass.CHARACTER,
            nwItemClass.WORLD,
            nwItemClass.TIMELINE,
            nwItemClass.OBJECT,
            nwItemClass.ENTITY,
        ],
        "numChapters":
        3,
        "numScenes":
        3,
        "chFolders":
        True,
    }
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)

    assert theProject.newProject(projData) is True
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True

    copyfile(projFile, testFile)
    assert cmpFiles(testFile, compFile, [2, 6, 7, 8])
コード例 #15
0
def testCoreProject_NewSampleA(fncDir, tmpConf, mockGUI, tmpDir):
    """Check that we can create a new project can be created from the
    provided sample project via a zip file.
    """
    projData = {
        "projName": "Test Sample",
        "projTitle": "Test Novel",
        "projAuthors": "Jane Doe\nJohn Doh\n",
        "projPath": fncDir,
        "popSample": True,
        "popMinimal": False,
        "popCustom": False,
    }
    theProject = NWProject(mockGUI)
    theProject.projTree.setSeed(42)

    # Sample set, but no path
    assert not theProject.newProject({"popSample": True})

    # Force the lookup path for assets to our temp folder
    srcSample = os.path.abspath(os.path.join(tmpConf.appRoot, "sample"))
    dstSample = os.path.join(tmpDir, "sample.zip")
    tmpConf.assetPath = tmpDir

    # Create and open a defective zip file
    with open(dstSample, mode="w+") as outFile:
        outFile.write("foo")

    assert not theProject.newProject(projData)
    os.unlink(dstSample)

    # Create a real zip file, and unpack it
    with ZipFile(dstSample, "w") as zipObj:
        zipObj.write(os.path.join(srcSample, "nwProject.nwx"), "nwProject.nwx")
        for docFile in os.listdir(os.path.join(srcSample, "content")):
            srcDoc = os.path.join(srcSample, "content", docFile)
            zipObj.write(srcDoc, "content/" + docFile)

    assert theProject.newProject(projData) is True
    assert theProject.openProject(fncDir) is True
    assert theProject.projName == "Sample Project"
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True
    os.unlink(dstSample)
コード例 #16
0
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpDir):
    """Test writing the ToC.txt file.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    for tHandle, pHandle, nwItem in mockItems:
        theTree.append(tHandle, pHandle, nwItem)
        theTree.updateItemData(tHandle)

    assert len(theTree) == len(mockItems)
    theTree._treeOrder.append("stuff")

    def mockIsFile(fileName):
        """Return True for items that are files in novelWriter and
        should thus also be files in the project folder structure.
        """
        dItem = theTree[fileName[8:21]]
        assert dItem is not None
        return dItem.itemType == nwItemType.FILE

    monkeypatch.setattr("os.path.isfile", mockIsFile)

    theProject.projContent = "content"
    theProject.projPath = None
    assert not theTree.writeToCFile()

    theProject.projPath = tmpDir
    assert theTree.writeToCFile()

    pathA = os.path.join("content", "c000000000001.nwd")
    pathB = os.path.join("content", "c000000000002.nwd")
    pathC = os.path.join("content", "b000000000002.nwd")

    assert readFile(os.path.join(tmpDir, nwFiles.TOC_TXT)) == (
        "\n"
        "Table of Contents\n"
        "=================\n"
        "\n"
        "File Name                  Class      Layout    Document Label\n"
        "--------------------------------------------------------------\n"
        f"{pathA}  NOVEL      DOCUMENT  Chapter One\n"
        f"{pathB}  NOVEL      DOCUMENT  Scene One\n"
        f"{pathC}  CHARACTER  NOTE      Jane Doe\n")
コード例 #17
0
def testCoreIndex_ScanThis(mockGUI):
    """Test the tag scanner function scanThis.
    """
    theProject = NWProject(mockGUI)
    theIndex = theProject.index

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

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

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

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

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

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

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

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

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

    assert theProject.closeProject() is True
コード例 #18
0
def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI):
    """Create a new project from a project wizard dictionary. With
    default setting, creating a Minimal project.
    """
    projFile = os.path.join(fncDir, "nwProject.nwx")
    testFile = os.path.join(outDir, "coreProject_NewMinimal_nwProject.nwx")
    compFile = os.path.join(refDir, "coreProject_NewMinimal_nwProject.nwx")

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

    # Setting no data should fail
    assert theProject.newProject({}) is False

    # Wrong type should also fail
    assert theProject.newProject("stuff") is False

    # Try again with a proper path
    assert theProject.newProject({"projPath": fncDir}) is True
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True

    # Creating the project once more should fail
    assert theProject.newProject({"projPath": fncDir}) is False

    # Open again
    assert theProject.openProject(projFile) is True

    # Save and close
    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

    # Open a second time
    assert theProject.openProject(projFile) is True
    assert theProject.openProject(projFile) is False
    assert theProject.openProject(projFile, overrideLock=True) is True
    assert theProject.saveProject() is True
    assert theProject.closeProject() is True
    copyfile(projFile, testFile)
    assert cmpFiles(testFile, compFile, [2, 6, 7, 8])
コード例 #19
0
def testCoreProject_Helpers(monkeypatch, fncDir, mockGUI):
    """Test helper functions for the project folder.
    """
    theProject = NWProject(mockGUI)

    # No path
    assert theProject.ensureFolderStructure() is False

    # Set the correct dir
    theProject.projPath = fncDir

    # Block user's home folder
    with monkeypatch.context() as mp:
        mp.setattr("os.path.expanduser", lambda *a, **k: fncDir)
        assert theProject.ensureFolderStructure() is False

    # Create a file to block meta folder
    metaDir = os.path.join(fncDir, "meta")
    writeFile(metaDir, "stuff")
    assert theProject.ensureFolderStructure() is False
    os.unlink(metaDir)

    # Create a file to block cache folder
    cacheDir = os.path.join(fncDir, "cache")
    writeFile(cacheDir, "stuff")
    assert theProject.ensureFolderStructure() is False
    os.unlink(cacheDir)

    # Create a file to block content folder
    contentDir = os.path.join(fncDir, "content")
    writeFile(contentDir, "stuff")
    assert theProject.ensureFolderStructure() is False
    os.unlink(contentDir)

    # Now, do it right
    assert theProject.ensureFolderStructure() is True
    assert os.path.isdir(metaDir)
    assert os.path.isdir(cacheDir)
    assert os.path.isdir(contentDir)
コード例 #20
0
def testCoreTree_MakeHandles(monkeypatch, mockGUI):
    """Test generating item handles.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    theTree.setSeed(42)

    tHandle = theTree._makeHandle()
    assert tHandle == "73475cb40a568"

    # Add the next in line to the project to force duplicate
    theTree._projTree["44cb730c42048"] = None
    tHandle = theTree._makeHandle()
    assert tHandle == "71ee45a3c0db9"

    # Fix the time() function and force a handle collission
    theTree.setSeed(None)
    theTree._handleCount = 0
    monkeypatch.setattr("novelwriter.core.tree.time", lambda: 123.4)

    tHandle = theTree._makeHandle()
    theTree._projTree[tHandle] = None
    newSeed = "123.4_0_"
    assert tHandle == sha256(newSeed.encode()).hexdigest()[0:13]

    tHandle = theTree._makeHandle()
    theTree._projTree[tHandle] = None
    newSeed = "123.4_1_"
    assert tHandle == sha256(newSeed.encode()).hexdigest()[0:13]

    # Reset the count and the handle for 0 and 1 should be duplicates
    # which forces the function to add the '!'
    theTree._handleCount = 0
    tHandle = theTree._makeHandle()
    theTree._projTree[tHandle] = None
    newSeed = "123.4_1_!"
    assert tHandle == sha256(newSeed.encode()).hexdigest()[0:13]
コード例 #21
0
def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI):
    """Check that new root folders can be added to the project.
    """
    projFile = os.path.join(fncDir, "nwProject.nwx")
    testFile = os.path.join(outDir, "coreProject_NewRoot_nwProject.nwx")
    compFile = os.path.join(refDir, "coreProject_NewRoot_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.newRoot("Novel", nwItemClass.NOVEL),
                      type(None))
    assert isinstance(theProject.newRoot("Plot", nwItemClass.PLOT), type(None))
    assert isinstance(theProject.newRoot("Character", nwItemClass.CHARACTER),
                      type(None))
    assert isinstance(theProject.newRoot("World", nwItemClass.WORLD),
                      type(None))
    assert isinstance(theProject.newRoot("Timeline", nwItemClass.TIMELINE),
                      str)
    assert isinstance(theProject.newRoot("Object", nwItemClass.OBJECT), str)
    assert isinstance(theProject.newRoot("Custom1", nwItemClass.CUSTOM), str)
    assert isinstance(theProject.newRoot("Custom2", nwItemClass.CUSTOM), str)

    assert theProject.projChanged is True
    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
コード例 #22
0
def mockItems(mockGUI):
    """Create a list of mock items.
    """
    theProject = NWProject(mockGUI)

    itemA = NWItem(theProject)
    itemA._name = "Novel"
    itemA._type = nwItemType.ROOT
    itemA._class = nwItemClass.NOVEL
    itemA._expanded = True

    itemB = NWItem(theProject)
    itemB._name = "Act One"
    itemB._type = nwItemType.FOLDER
    itemB._class = nwItemClass.NOVEL
    itemB._expanded = True

    itemC = NWItem(theProject)
    itemC._name = "Chapter One"
    itemC._type = nwItemType.FILE
    itemC._class = nwItemClass.NOVEL
    itemC._layout = nwItemLayout.DOCUMENT
    itemC._charCount = 300
    itemC._wordCount = 50
    itemC._paraCount = 2

    itemD = NWItem(theProject)
    itemD._name = "Scene One"
    itemD._type = nwItemType.FILE
    itemD._class = nwItemClass.NOVEL
    itemD._layout = nwItemLayout.DOCUMENT
    itemD._charCount = 3000
    itemD._wordCount = 500
    itemD._paraCount = 20

    itemE = NWItem(theProject)
    itemE._name = "Outtakes"
    itemE._type = nwItemType.ROOT
    itemE._class = nwItemClass.ARCHIVE
    itemE._expanded = False

    itemF = NWItem(theProject)
    itemF._name = "Trash"
    itemF._type = nwItemType.TRASH
    itemF._class = nwItemClass.TRASH
    itemF._expanded = False

    itemG = NWItem(theProject)
    itemG._name = "Characters"
    itemG._type = nwItemType.ROOT
    itemG._class = nwItemClass.CHARACTER
    itemG._expanded = True

    itemH = NWItem(theProject)
    itemH._name = "Jane Doe"
    itemH._type = nwItemType.FILE
    itemH._class = nwItemClass.CHARACTER
    itemH._layout = nwItemLayout.NOTE
    itemH._charCount = 2000
    itemH._wordCount = 400
    itemH._paraCount = 16

    theItems = [
        ("a000000000001", None, itemA),
        ("b000000000001", "a000000000001", itemB),
        ("c000000000001", "b000000000001", itemC),
        ("c000000000002", "b000000000001", itemD),
        ("a000000000002", None, itemE),
        ("a000000000003", None, itemF),
        ("a000000000004", None, itemG),
        ("b000000000002", "a000000000002", itemH),
    ]

    return theItems
コード例 #23
0
def testCoreTree_BuildTree(mockGUI, mockItems):
    """Test building a project tree from a list of items.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    theTree.setSeed(42)
    assert theTree._handleSeed == 42

    # Check that tree is empty (calls NWTree.__bool__)
    assert not theTree

    # Check for archive and trash folders
    assert theTree.trashRoot() is None
    assert theTree.archiveRoot() is None
    assert not theTree.isTrashRoot("a000000000003")

    aHandles = []
    for tHandle, pHandle, nwItem in mockItems:
        aHandles.append(tHandle)
        assert theTree.append(tHandle, pHandle, nwItem)

    assert theTree._treeChanged

    # Check that tree is not empty (calls __bool__)
    assert theTree

    # Check the number of elements (calls __len__)
    assert len(theTree) == len(mockItems)

    # Check that we have the correct handles
    assert theTree.handles() == aHandles

    # Check by iterator (calls __iter__, __next__ and __getitem__)
    for theItem, theHandle in zip(theTree, aHandles):
        assert theItem.itemHandle == theHandle

    # Check that we have the correct archive and trash folders
    assert theTree.trashRoot() == "a000000000003"
    assert theTree.archiveRoot() == "a000000000002"
    assert theTree.isTrashRoot("a000000000003")

    # Try to add another trash folder
    itemT = NWItem(theProject)
    itemT._name = "Trash"
    itemT._type = nwItemType.TRASH
    itemT._class = nwItemClass.TRASH
    itemT._expanded = False

    assert not theTree.append("1234567890abc", None, itemT)
    assert len(theTree) == len(mockItems)

    # Generate handle automatically
    itemT = NWItem(theProject)
    itemT._name = "New File"
    itemT._type = nwItemType.FILE
    itemT._class = nwItemClass.NOVEL
    itemT._layout = nwItemLayout.DOCUMENT

    assert theTree.append(None, None, itemT)
    assert len(theTree) == len(mockItems) + 1

    theList = theTree.handles()
    assert theList[-1] == "73475cb40a568"

    # Try to add existing handle
    assert not theTree.append("73475cb40a568", None, itemT)
    assert len(theTree) == len(mockItems) + 1

    # Delete a non-existing item
    del theTree["stuff"]
    assert len(theTree) == len(mockItems) + 1

    # Delete the last item
    del theTree["73475cb40a568"]
    assert len(theTree) == len(mockItems)
    assert "73475cb40a568" not in theTree

    # Delete the Novel, Archive and Trash folders
    del theTree["a000000000001"]
    assert len(theTree) == len(mockItems) - 1
    assert "a000000000001" not in theTree

    del theTree["a000000000002"]
    assert len(theTree) == len(mockItems) - 2
    assert "a000000000002" not in theTree
    assert theTree.archiveRoot() is None

    del theTree["a000000000003"]
    assert len(theTree) == len(mockItems) - 3
    assert "a000000000003" not in theTree
    assert theTree.trashRoot() is None
コード例 #24
0
def testCoreIndex_CheckFileIndex(mockGUI):
    """Test the file index checker.
    """
    theProject = NWProject(mockGUI)
    theIndex = NWIndex(theProject)

    # Valid Index
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    theIndex._fileIndex = theIndex._fileIndex.copy()
    assert theIndex._checkFileIndex() is None

    # Invalid Handle
    theIndex._fileIndex = {
        "H3b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Invalid Title
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "INVALID": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

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

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

    # Missing 'level'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "stuff": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'title'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "stuff": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'layout'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "stuff": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'cCount'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "stuff": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'wCount'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "stuff": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'pCount'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "stuff": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

    # Missing 'synopsis'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "stuff": "text",
            }
        }
    }
    with pytest.raises(KeyError):
        theIndex._checkFileIndex()

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

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

    # Wrong Type for 'title'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": 12345678,
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": "text",
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkFileIndex()

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

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

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

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

    # Wrong Type for 'synopsis'
    theIndex._fileIndex = {
        "53b69b83cdafc": {
            "T000001": {
                "level": "H1",
                "title": "My Novel",
                "layout": "DOCUMENT",
                "cCount": 72,
                "wCount": 15,
                "pCount": 2,
                "synopsis": 123456,
            }
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkFileIndex()
コード例 #25
0
def testCoreIndex_CheckRefIndex(mockGUI):
    """Test the reference index checker.
    """
    theProject = NWProject(mockGUI)
    theIndex = NWIndex(theProject)

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

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

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

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

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

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

    # Wrong Type of Entry 2
    theIndex._refIndex = {
        "6a2d6d5f4f401": {
            "T000000": [],
            "T000001": [[3, "@pov", "Jane"], [4, "@location", 123456]],
        }
    }
    with pytest.raises(ValueError):
        theIndex._checkRefIndex()
コード例 #26
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!")
    ]
コード例 #27
0
def testCoreIndex_LoadSave(monkeypatch, nwLipsum, mockGUI, 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(mockGUI)
    theProject.projTree.setSeed(42)
    assert theProject.openProject(nwLipsum)

    theIndex = NWIndex(theProject)
    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 theIndex.reIndexHandle(None) is False

    # Make the save fail
    with monkeypatch.context() as mp:
        mp.setattr("builtins.open", causeException)
        assert theIndex.saveIndex() is False

    # Make the save pass
    assert theIndex.saveIndex() is True

    # Take a copy of the index
    tagIndex = str(theIndex._tagIndex)
    refIndex = str(theIndex._refIndex)
    fileIndex = str(theIndex._fileIndex)
    textCounts = str(theIndex._fileMeta)

    # Delete a handle
    assert theIndex._tagIndex.get("Bod", None) is not None
    assert theIndex._refIndex.get("4c4f28287af27", None) is not None
    assert theIndex._fileIndex.get("4c4f28287af27", None) is not None
    assert theIndex._fileMeta.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._fileIndex.get("4c4f28287af27", None) is None
    assert theIndex._fileMeta.get("4c4f28287af27", None) is None

    # Clear the index
    theIndex.clearIndex()
    assert theIndex._tagIndex == {}
    assert theIndex._refIndex == {}
    assert theIndex._fileIndex == {}
    assert theIndex._fileMeta == {}

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

    # Make the load pass
    assert theIndex.loadIndex() is True

    assert str(theIndex._tagIndex) == tagIndex
    assert str(theIndex._refIndex) == refIndex
    assert str(theIndex._fileIndex) == fileIndex
    assert str(theIndex._fileMeta) == textCounts

    # Break the index and check that we notice
    assert theIndex.indexBroken is False
    theIndex._tagIndex["Bod"].append("Stuff")
    theIndex._checkIndex()
    assert theIndex.indexBroken is True

    # Finalise
    assert theProject.closeProject() is True

    copyfile(projFile, testFile)
    assert cmpFiles(testFile, compFile)
コード例 #28
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
コード例 #29
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
コード例 #30
0
def testCoreTree_Methods(mockGUI, mockItems):
    """Test various class methods.
    """
    theProject = NWProject(mockGUI)
    theTree = NWTree(theProject)

    for tHandle, pHandle, nwItem in mockItems:
        theTree.append(tHandle, pHandle, nwItem)
        theTree.updateItemData(tHandle)

    assert len(theTree) == len(mockItems)

    # Update item data, nonsense handle
    assert theTree.updateItemData("stuff") is False

    # Update item data, invalid item parent
    corrParent = theTree["b000000000001"].itemParent
    theTree["b000000000001"].setParent("0000000000000")
    assert theTree.updateItemData("b000000000001") is False

    # Update item data, valid item parent
    theTree["b000000000001"].setParent(corrParent)
    assert theTree.updateItemData("b000000000001") is True

    # Update item data, root is unreachable
    maxDepth = theTree.MAX_DEPTH
    theTree.MAX_DEPTH = 0
    with pytest.raises(RecursionError):
        theTree.updateItemData("b000000000001")
    theTree.MAX_DEPTH = maxDepth

    # Chech type
    assert theTree.checkType("blabla", nwItemType.FILE) is False
    assert theTree.checkType("b000000000001", nwItemType.FILE) is False
    assert theTree.checkType("c000000000001", nwItemType.FILE) is True

    # Root item lookup
    assert theTree.findRoot(nwItemClass.WORLD) is None
    assert theTree.findRoot(nwItemClass.NOVEL) == "a000000000001"
    assert theTree.findRoot(nwItemClass.CHARACTER) == "a000000000004"

    # Add a fake item to root and check that it can handle it
    theTree._treeRoots["0000000000000"] = NWItem(theProject)
    assert theTree.findRoot(nwItemClass.WORLD) is None
    del theTree._treeRoots["0000000000000"]

    # Get item path
    assert theTree.getItemPath("stuff") == []
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001", "a000000000001"
    ]

    # Cause recursion error
    maxDepth = theTree.MAX_DEPTH
    theTree.MAX_DEPTH = 0
    with pytest.raises(RecursionError):
        theTree.getItemPath("c000000000001")
    theTree.MAX_DEPTH = maxDepth

    # Break the folder parent handle
    theTree["b000000000001"]._parent = "stuff"
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001"
    ]

    theTree["b000000000001"]._parent = "a000000000001"
    assert theTree.getItemPath("c000000000001") == [
        "c000000000001", "b000000000001", "a000000000001"
    ]

    # Change file layout
    assert theTree.setFileItemLayout("stuff", nwItemLayout.DOCUMENT) is False
    assert theTree.setFileItemLayout("b000000000001",
                                     nwItemLayout.DOCUMENT) is False
    assert theTree.setFileItemLayout("c000000000001", "stuff") is False
    assert theTree.setFileItemLayout("c000000000001",
                                     nwItemLayout.NOTE) is True
    assert theTree["c000000000001"].itemLayout == nwItemLayout.NOTE