From 5a685474ffa2e0710c98ce579bafc5a984640c96 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Wed, 17 Feb 2021 16:31:37 +0100 Subject: [PATCH] Move the remanining two functions in the tools.py file to other source files --- nw/common.py | 23 ++++++ nw/core/__init__.py | 4 +- nw/core/index.py | 66 +++++++++++++++- nw/core/tokenizer.py | 2 +- nw/core/tools.py | 118 ---------------------------- nw/gui/projdetails.py | 2 +- tests/test_base/test_base_common.py | 29 ++++++- tests/test_core/test_core_index.py | 33 +++++++- tests/test_core/test_core_tools.py | 83 ------------------- 9 files changed, 149 insertions(+), 211 deletions(-) delete mode 100644 nw/core/tools.py delete mode 100644 tests/test_core/test_core_tools.py diff --git a/nw/common.py b/nw/common.py index 826f7370..4464f287 100644 --- a/nw/common.py +++ b/nw/common.py @@ -311,3 +311,26 @@ def getGuiItem(theName): if qWidget.objectName() == theName: return qWidget return None + +def numberToRoman(numVal, isLower=False): + """Convert an integer to a roman number. + """ + if not isinstance(numVal, int): + return "NAN" + if numVal < 1 or numVal > 4999: + return "OOR" + + theValues = [ + (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), + (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"), + ] + + romNum = "" + for theDiv, theSym in theValues: + n = numVal//theDiv + romNum += n*theSym + numVal -= n*theDiv + if numVal <= 0: + break + + return romNum.lower() if isLower else romNum diff --git a/nw/core/__init__.py b/nw/core/__init__.py index be0aeeb2..f79492a3 100644 --- a/nw/core/__init__.py +++ b/nw/core/__init__.py @@ -1,17 +1,15 @@ # -*- coding: utf-8 -*- from nw.core.document import NWDoc -from nw.core.index import NWIndex +from nw.core.index import NWIndex, countWords from nw.core.project import NWProject from nw.core.spellcheck import NWSpellCheck, NWSpellEnchant, NWSpellSimple from nw.core.tohtml import ToHtml from nw.core.toodt import ToOdt from nw.core.tomd import ToMarkdown -from nw.core.tools import countWords, numberToRoman __all__ = [ "countWords", - "numberToRoman", "NWDoc", "NWIndex", "NWProject", diff --git a/nw/core/index.py b/nw/core/index.py index f6bdf0ae..93aed47e 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -5,7 +5,8 @@ novelWriter – Project Index Data class for the project index of tags, headers and references File History: -Created: 2019-05-27 [0.1.4] +Created: 2019-04-22 [0.0.1] countWords +Created: 2019-05-27 [0.1.4] NWIndex This file is a part of novelWriter Copyright 2018–2021, Veronica Berglyd Olsen @@ -32,10 +33,10 @@ import os from time import time from nw.constants import ( - nwFiles, nwKeyWords, nwItemType, nwItemClass, nwItemLayout, nwAlert + nwFiles, nwKeyWords, nwItemType, nwItemClass, nwItemLayout, nwAlert, + nwUnicode ) from nw.core.document import NWDoc -from nw.core.tools import countWords from nw.common import isHandle, isTitleTag, isItemClass, isItemLayout logger = logging.getLogger(__name__) @@ -906,3 +907,62 @@ class NWIndex(): return # END Class NWIndex + +# =============================================================================================== # +# Simple Word Counter +# =============================================================================================== # + +def countWords(theText): + """Count words in a piece of text, skipping special syntax and + comments. + """ + charCount = 0 + wordCount = 0 + paraCount = 0 + prevEmpty = True + + # We need to treat dashes as word separators for counting words. + # The check+replace apprach is much faster that direct replace for + # large texts, and a bit slower for small texts, but in the latter + # case it doesn't matter. + if nwUnicode.U_ENDASH in theText: + theText = theText.replace(nwUnicode.U_ENDASH, " ") + if nwUnicode.U_EMDASH in theText: + theText = theText.replace(nwUnicode.U_EMDASH, " ") + + for aLine in theText.splitlines(): + + countPara = True + theLen = len(aLine) + + if theLen == 0: + prevEmpty = True + continue + if aLine[0] == "@" or aLine[0] == "%": + continue + + if aLine[0:5] == "#### ": + wordCount -= 1 + charCount -= 5 + countPara = False + elif aLine[0:4] == "### ": + wordCount -= 1 + charCount -= 4 + countPara = False + elif aLine[0:3] == "## ": + wordCount -= 1 + charCount -= 3 + countPara = False + elif aLine[0:2] == "# ": + wordCount -= 1 + charCount -= 2 + countPara = False + + wordCount += len(aLine.split()) + charCount += theLen + if countPara and prevEmpty: + paraCount += 1 + + prevEmpty = not countPara + + return charCount, wordCount, paraCount diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index 260a230e..989db48f 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -33,7 +33,7 @@ from functools import partial from PyQt5.QtCore import QCoreApplication, QRegularExpression from nw.core.document import NWDoc -from nw.core.tools import numberToRoman +from nw.common import numberToRoman from nw.constants import nwConst, nwUnicode, nwItemLayout, nwItemType, nwRegEx logger = logging.getLogger(__name__) diff --git a/nw/core/tools.py b/nw/core/tools.py deleted file mode 100644 index a3dff45b..00000000 --- a/nw/core/tools.py +++ /dev/null @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- -""" -novelWriter – Various Tools -=========================== -Various core tool functions - -File History: -Created: 2019-04-22 [0.0.1] countWords -Created: 2020-07-05 [0.10.0] numberToRoman - -This file is a part of novelWriter -Copyright 2018–2021, Veronica Berglyd Olsen - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -import logging - -from nw.constants import nwUnicode - -logger = logging.getLogger(__name__) - -# =============================================================================================== # -# Simple Word Counter -# =============================================================================================== # - -def countWords(theText): - """Count words in a piece of text, skipping special syntax and - comments. - """ - charCount = 0 - wordCount = 0 - paraCount = 0 - prevEmpty = True - - # We need to treat dashes as word separators for counting words. - # The check+replace apprach is much faster that direct replace for - # large texts, and a bit slower for small texts, but in the latter - # case it doesn't matter. - if nwUnicode.U_ENDASH in theText: - theText = theText.replace(nwUnicode.U_ENDASH, " ") - if nwUnicode.U_EMDASH in theText: - theText = theText.replace(nwUnicode.U_EMDASH, " ") - - for aLine in theText.splitlines(): - - countPara = True - theLen = len(aLine) - - if theLen == 0: - prevEmpty = True - continue - if aLine[0] == "@" or aLine[0] == "%": - continue - - if aLine[0:5] == "#### ": - wordCount -= 1 - charCount -= 5 - countPara = False - elif aLine[0:4] == "### ": - wordCount -= 1 - charCount -= 4 - countPara = False - elif aLine[0:3] == "## ": - wordCount -= 1 - charCount -= 3 - countPara = False - elif aLine[0:2] == "# ": - wordCount -= 1 - charCount -= 2 - countPara = False - - wordCount += len(aLine.split()) - charCount += theLen - if countPara and prevEmpty: - paraCount += 1 - - prevEmpty = not countPara - - return charCount, wordCount, paraCount - -# =============================================================================================== # -# Convert an Integer to a Roman Number -# =============================================================================================== # - -def numberToRoman(numVal, isLower=False): - """Convert an integer to a roman number. - """ - if not isinstance(numVal, int): - return "NAN" - if numVal < 1 or numVal > 4999: - return "OOR" - - theValues = [ - (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), (90, "XC"), - (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I"), - ] - - romNum = "" - for theDiv, theSym in theValues: - n = numVal//theDiv - romNum += n*theSym - numVal -= n*theDiv - if numVal <= 0: - break - - return romNum.lower() if isLower else romNum diff --git a/nw/gui/projdetails.py b/nw/gui/projdetails.py index 1ee40f6f..ba393261 100644 --- a/nw/gui/projdetails.py +++ b/nw/gui/projdetails.py @@ -37,7 +37,7 @@ from PyQt5.QtWidgets import ( from nw.gui.custom import PagedDialog, QSwitch from nw.constants import nwUnicode -from nw.core import numberToRoman +from nw.common import numberToRoman logger = logging.getLogger(__name__) diff --git a/tests/test_base/test_base_common.py b/tests/test_base/test_base_common.py index 4b076a64..03c408cd 100644 --- a/tests/test_base/test_base_common.py +++ b/tests/test_base/test_base_common.py @@ -27,7 +27,7 @@ from nw.common import ( checkString, checkBool, checkInt, colRange, formatInt, transferCase, fuzzyTime, checkHandle, formatTimeStamp, formatTime, hexToInt, makeFileNameSafe, isHandle, isTitleTag, isItemClass, isItemType, - isItemLayout + isItemLayout, numberToRoman ) from tools import cmpList @@ -325,3 +325,30 @@ def testBaseCommon_MakeFileNameSafe(): assert makeFileNameSafe("aaaa bbbb") == "aaaa bbbb" # END Test testBaseCommon_MakeFileNameSafe + +@pytest.mark.core +def testBaseCommon_RomanNumbers(): + """Test conversion of integers to Roman numbers. + """ + assert numberToRoman(None, False) == "NAN" + assert numberToRoman(0, False) == "OOR" + assert numberToRoman(1, False) == "I" + assert numberToRoman(2, False) == "II" + assert numberToRoman(3, False) == "III" + assert numberToRoman(4, False) == "IV" + assert numberToRoman(5, False) == "V" + assert numberToRoman(6, False) == "VI" + assert numberToRoman(7, False) == "VII" + assert numberToRoman(8, False) == "VIII" + assert numberToRoman(9, False) == "IX" + assert numberToRoman(10, False) == "X" + assert numberToRoman(14, False) == "XIV" + assert numberToRoman(42, False) == "XLII" + assert numberToRoman(99, False) == "XCIX" + assert numberToRoman(142, False) == "CXLII" + assert numberToRoman(542, False) == "DXLII" + assert numberToRoman(999, False) == "CMXCIX" + assert numberToRoman(2010, False) == "MMX" + assert numberToRoman(999, True) == "cmxcix" + +# END Test testBaseCommon_RomanNumbers diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index 9b1c656a..2d5f8f12 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -29,7 +29,7 @@ from shutil import copyfile from tools import cmpFiles from nw.core.project import NWProject -from nw.core.index import NWIndex +from nw.core.index import NWIndex, countWords from nw.constants import nwItemClass, nwItemLayout @pytest.mark.core @@ -1161,3 +1161,34 @@ def testCoreIndex_CheckTextCounts(dummyGUI): theIndex._checkTextCounts() # END Test testCoreIndex_CheckTextCounts + +@pytest.mark.core +def testCoreIndex_CountWords(): + """Test the word counter and the exclusion filers. + """ + testText = ( + "# Heading One\n" + "## Heading Two\n" + "### Heading Three\n" + "#### Heading Four\n" + "\n" + "@tag: value\n" + "\n" + "% A comment that should n ot be counted.\n" + "\n" + "The first paragraph.\n" + "\n" + "The second paragraph.\n" + "\n" + "\n" + "The third paragraph.\n" + "\n" + "Dashes\u2013and even longer\u2014dashes." + ) + cC, wC, pC = countWords(testText) + + assert cC == 138 + assert wC == 22 + assert pC == 4 + +# END Test testCoreIndex_CountWords diff --git a/tests/test_core/test_core_tools.py b/tests/test_core/test_core_tools.py deleted file mode 100644 index 77faf444..00000000 --- a/tests/test_core/test_core_tools.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -""" -novelWriter – Core Tools Tester -=============================== - -This file is a part of novelWriter -Copyright 2018–2021, Veronica Berglyd Olsen - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -import pytest - -from nw.core.tools import countWords, numberToRoman - -@pytest.mark.core -def testCoreTools_CountWords(): - """Test the word counter and the exclusion filers. - """ - testText = ( - "# Heading One\n" - "## Heading Two\n" - "### Heading Three\n" - "#### Heading Four\n" - "\n" - "@tag: value\n" - "\n" - "% A comment that should n ot be counted.\n" - "\n" - "The first paragraph.\n" - "\n" - "The second paragraph.\n" - "\n" - "\n" - "The third paragraph.\n" - "\n" - "Dashes\u2013and even longer\u2014dashes." - ) - cC, wC, pC = countWords(testText) - - assert cC == 138 - assert wC == 22 - assert pC == 4 - -# END Test testCoreTools_CountWords - -@pytest.mark.core -def testCoreTools_RomanNumbers(): - """Test conversion of integers to Roman numbers. - """ - assert numberToRoman(None, False) == "NAN" - assert numberToRoman(0, False) == "OOR" - assert numberToRoman(1, False) == "I" - assert numberToRoman(2, False) == "II" - assert numberToRoman(3, False) == "III" - assert numberToRoman(4, False) == "IV" - assert numberToRoman(5, False) == "V" - assert numberToRoman(6, False) == "VI" - assert numberToRoman(7, False) == "VII" - assert numberToRoman(8, False) == "VIII" - assert numberToRoman(9, False) == "IX" - assert numberToRoman(10, False) == "X" - assert numberToRoman(14, False) == "XIV" - assert numberToRoman(42, False) == "XLII" - assert numberToRoman(99, False) == "XCIX" - assert numberToRoman(142, False) == "CXLII" - assert numberToRoman(542, False) == "DXLII" - assert numberToRoman(999, False) == "CMXCIX" - assert numberToRoman(2010, False) == "MMX" - assert numberToRoman(999, True) == "cmxcix" - -# END Test testCoreTools_RomanNumbers