Remove the difflib spellchecker (#875)

* Delete simple spell checker
* Clean up the spell checker code
* Update tests
* Delete the bundled dictionaries
* Update documentation
* Use set() for user word list
* Fix tests so they pass also without dictionaries installed
This commit is contained in:
Veronica Berglyd Olsen
2021-08-30 22:39:27 +02:00
committed by GitHub
parent 4b52f343c1
commit f6845a9820
24 changed files with 151 additions and 374876 deletions
+1 -2
View File
@@ -1,5 +1,5 @@
[Main]
timestamp = 2021-08-26 17:48:02
timestamp = 2021-08-30 21:27:27
theme = default
syntax = default_light
icons = typicons_light
@@ -53,7 +53,6 @@ fmtdoublequote = “, ”
fmtpadbefore =
fmtpadafter =
fmtpadthin = False
spelltool = internal
spellcheck = en
showtabsnspaces = False
showlineendings = False
@@ -1,5 +1,5 @@
[Main]
timestamp = 2021-08-26 17:48:04
timestamp = 2021-08-30 21:45:17
theme = default
syntax = default_light
icons = typicons_light
@@ -53,7 +53,6 @@ fmtdoublequote = “, ”
fmtpadbefore =
fmtpadafter =
fmtpadthin = False
spelltool = internal
spellcheck = en
showtabsnspaces = True
showlineendings = True
+1 -2
View File
@@ -29,7 +29,7 @@ from mock import causeOSError, MockApp
from tools import cmpFiles, writeFile
from novelwriter.config import Config
from novelwriter.constants import nwConst, nwFiles
from novelwriter.constants import nwFiles
@pytest.mark.base
@@ -133,7 +133,6 @@ def testBaseConfig_Init(monkeypatch, tmpDir, fncDir, outDir, refDir, filesDir):
# This should create a config file as well
with monkeypatch.context() as mp:
mp.setattr("os.path.expanduser", lambda *a: "")
tstConf.spellTool = nwConst.SP_INTERNAL
tstConf.initConfig(confPath=tmpDir, dataPath=tmpDir)
assert tstConf.confPath == tmpDir
assert tstConf.dataPath == tmpDir
+23 -113
View File
@@ -26,53 +26,7 @@ import pytest
from mock import causeOSError
from tools import readFile, writeFile
from novelwriter.core.spellcheck import (
NWSpellCheck, NWSpellEnchant, NWSpellSimple
)
@pytest.mark.core
def testCoreSpell_Super(monkeypatch, tmpDir):
"""Test the spell checker super class
"""
wList = os.path.join(tmpDir, "wordlist.txt")
writeFile(wList, "a_word\nb_word\nc_word\n")
spChk = NWSpellCheck()
# Check that default functions return results that reflects that spell
# checking is effectively disabled
assert spChk.setLanguage("", "") is None
assert spChk.checkWord("")
assert spChk.suggestWords("") == []
assert spChk.listDictionaries() == []
assert spChk.describeDict() == ("", "")
# Add a word to the user's dictionary
assert spChk._readProjectDictionary("stuff") is False
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert spChk._readProjectDictionary(wList) is False
assert spChk._readProjectDictionary(None) is False
assert spChk._readProjectDictionary(wList) is True
assert spChk.projectDict == wList
# Cannot write to file
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert spChk.addWord("d_word") is False
assert readFile(wList) == "a_word\nb_word\nc_word\n"
# First time, OK
assert spChk.addWord("d_word") is True
assert readFile(wList) == "a_word\nb_word\nc_word\nd_word\n"
# But not added twice
assert spChk.addWord("d_word") is False
assert readFile(wList) == "a_word\nb_word\nc_word\nd_word\n"
# END Test testCoreSpell_Super
from novelwriter.core.spellcheck import NWSpellEnchant
@pytest.mark.core
@@ -99,11 +53,32 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
spChk.setLanguage("en", wList)
spChk.setLanguage("en", wList)
# Add a word to the user's dictionary
assert spChk._readProjectDictionary("stuff") is False
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert spChk._readProjectDictionary(wList) is False
assert spChk._readProjectDictionary(None) is False
assert spChk._readProjectDictionary(wList) is True
assert spChk.projectDict == wList
# Cannot write to file
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert spChk.addWord("d_word") is False
assert readFile(wList) == "a_word\nb_word\nc_word\n"
assert spChk.addWord("d_word") is True
assert readFile(wList) == "a_word\nb_word\nc_word\nd_word\n"
assert spChk.addWord("d_word") is False
# Check words
assert spChk.checkWord("a_word") is True
assert spChk.checkWord("b_word") is True
assert spChk.checkWord("c_word") is True
assert spChk.checkWord("d_word") is False
assert spChk.checkWord("d_word") is True
assert spChk.checkWord("e_word") is False
spChk.addWord("d_word")
assert spChk.checkWord("d_word") is True
@@ -120,68 +95,3 @@ def testCoreSpell_Enchant(monkeypatch, tmpDir):
assert aName != ""
# END Test testCoreSpell_Enchant
@pytest.mark.core
def testCoreSpell_Simple(monkeypatch, tmpDir):
"""Test the fallback simple spell checker
"""
wList = os.path.join(tmpDir, "wordlist.txt")
wDict = os.path.join(tmpDir, "en.dict")
writeFile(wList, "a_word\nb_word\nc_word\n")
writeFile(wDict, "# Comment\ne_word\nf_word\ng_word\n")
spChk = NWSpellSimple()
spChk.mainConf.dictPath = tmpDir
# Load dictionary, but fail
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
spChk.setLanguage("en", wList)
assert spChk.spellLanguage is None
assert spChk.theWords == set(spChk.projDict)
# Load dictionary properly
spChk.setLanguage("en", wList)
assert spChk.projDict == ["a_word", "b_word", "c_word"]
assert spChk.theWords == {"e_word", "f_word", "g_word", "a_word", "b_word", "c_word"}
# Check words
assert spChk.checkWord("a_word")
assert spChk.checkWord("b_word")
assert spChk.checkWord("c_word")
assert not spChk.checkWord("d_word")
assert spChk.checkWord("e_word")
assert spChk.checkWord("f_word")
assert spChk.checkWord("g_word")
# Add word
spChk.addWord("d_word")
assert spChk.checkWord("d_word")
# Check spelling
assert spChk.suggestWords(" \t") == []
wSuggest = spChk.suggestWords("d_wrod")
assert len(wSuggest) > 0
assert "d_word" in wSuggest
# Break the matching
with monkeypatch.context() as mp:
mp.setattr("difflib.get_close_matches", lambda *args, **kwargs: [""])
assert spChk.suggestWords("word") == []
# Capitalisation
wSuggest = spChk.suggestWords("D_wrod")
assert len(wSuggest) > 0
assert "D_word" in wSuggest
# List dictionaries
assert spChk.listDictionaries() == [("en", "difflib")]
# Description
aTag, aName = spChk.describeDict()
assert aTag == "en"
assert aName == ""
# END Test testCoreSpell_Simple
+2 -2
View File
@@ -33,7 +33,6 @@ from PyQt5.QtWidgets import (
from novelwriter.config import Config
from novelwriter.dialogs import GuiPreferences, GuiQuoteSelect
from novelwriter.constants import nwConst
keyDelay = 2
typeDelay = 1
@@ -67,10 +66,11 @@ def testDlgPreferences_Main(qtbot, monkeypatch, fncDir, outDir, refDir):
theConf = nwGUI.mainConf
assert theConf.confPath == fncDir
theConf.spellTool = nwConst.SP_INTERNAL
monkeypatch.setattr(GuiPreferences, "exec_", lambda *a: None)
monkeypatch.setattr(GuiPreferences, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
nwGUI.mainMenu.aPreferences.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiPreferences") is not None, timeout=1000)
@@ -66,6 +66,8 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj, outDi
# Get the dialog object
monkeypatch.setattr(GuiProjectSettings, "exec_", lambda *a: None)
monkeypatch.setattr(GuiProjectSettings, "result", lambda *a: QDialog.Accepted)
monkeypatch.setattr(nwGUI.docEditor.spEnchant, "listDictionaries", lambda: [("en", "none")])
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
qtbot.waitUntil(lambda: getGuiItem("GuiProjectSettings") is not None, timeout=1000)
-1
View File
@@ -229,7 +229,6 @@ def testGuiEditor_MetaData(qtbot, monkeypatch, nwGUI, nwMinimal):
assert nwGUI.docEditor.docHandle() == sHandle
assert nwGUI.docEditor.lastActive() > 0.0
assert nwGUI.docEditor.isEmpty() is False
assert nwGUI.docEditor.currentDictionary() is not None
# Cursor Position
assert nwGUI.docEditor.setCursorPosition(None) is False