Grammalecte  Check-in [759321730c]

Overview
Comment:[core][fr][py] gc_engine.py as primary module
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fr | core | gcerw
Files: files | file ages | folders
SHA3-256: 759321730cadb9e4a15c6a429101f85ac24a1d5f3ef635d3073ad755ecc5bec3
User & Date: olr on 2020-04-04 15:54:02
Original Comment: [core][fr] gc_engine.py as primary module
Other Links: branch diff | manifest | tags
Context
2020-04-05
08:39
[core][cli][graphsell][lo][py] move lexicographer from gc engine to graphspell check-in: ba3c939f60 user: olr tags: cli, core, gcerw, graphspell, lo
2020-04-04
15:54
[core][fr][py] gc_engine.py as primary module check-in: 759321730c user: olr tags: core, fr, gcerw
2020-04-03
23:39
[core][py] add gc_engine_func.py check-in: d12fb1528a user: olr tags: core, gcerw
Changes

Modified gc_core/py/__init__.py from [49f46a05ff] to [3c70db889b].

1
2
3
4
5
"""
Grammar checker
"""

from .grammar_checker import *




|
1
2
3
4
5
"""
Grammar checker
"""

from .${lang}.gc_engine import *

Deleted gc_core/py/grammar_checker.py version [50b054f72f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
"""
Grammalecte, grammar checker
"""

import importlib
import json

from . import text


class GrammarChecker:
    "GrammarChecker: Wrapper for the grammar checker engine"

    def __init__ (self, sLangCode, sContext="Python"):
        self.sLangCode = sLangCode
        # Grammar checker engine
        self.gce = importlib.import_module("."+sLangCode, "grammalecte")
        self.gce.load(sContext)
        # Spell checker
        self.oSpellChecker = self.gce.getSpellChecker()
        # Lexicographer
        self.oLexicographer = None
        # Text formatter
        self.oTextFormatter = None

    def getGCEngine (self):
        "return the grammar checker object"
        return self.gce

    def getSpellChecker (self):
        "return the spell checker object"
        return self.oSpellChecker

    def getTextFormatter (self):
        "load and return the text formatter"
        if self.oTextFormatter is None:
            tf = importlib.import_module("."+self.sLangCode+".textformatter", "grammalecte")
            self.oTextFormatter = tf.TextFormatter()
        return self.oTextFormatter

    def getLexicographer (self):
        "load and return the lexicographer"
        if self.oLexicographer is None:
            lxg = importlib.import_module("."+self.sLangCode+".lexicographe", "grammalecte")
            self.oLexicographer = lxg.Lexicographe(self.oSpellChecker)
        return self.oLexicographer

    def displayGCOptions (self):
        "display the grammar checker options"
        self.gce.displayOptions()

    def getParagraphErrors (self, sText, dOptions=None, bContext=False, bSpellSugg=False, bDebug=False):
        "returns a tuple: (grammar errors, spelling errors)"
        aGrammErrs = self.gce.parse(sText, "FR", bDebug=bDebug, dOptions=dOptions, bContext=bContext)
        aSpellErrs = self.oSpellChecker.parseParagraph(sText, bSpellSugg)
        return aGrammErrs, aSpellErrs

    def getParagraphWithErrors (self, sText, dOptions=None, bEmptyIfNoErrors=False, bSpellSugg=False, nWidth=100, bDebug=False):
        "parse text and return a readable text with underline errors"
        aGrammErrs, aSpellErrs = self.getParagraphErrors(sText, dOptions, False, bSpellSugg, bDebug)
        if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs:
            return ("", [])
        return text.generateParagraph(sText, aGrammErrs, aSpellErrs, nWidth)

    def getTextWithErrors (self, sText, bEmptyIfNoErrors=False, bSpellSugg=False, nWidth=100, bDebug=False):
        "[todo]"

    def getParagraphErrorsAsJSON (self, iIndex, sText, dOptions=None, bContext=False, bEmptyIfNoErrors=False, bSpellSugg=False, bReturnText=False, lLineSet=None, bDebug=False):
        "parse text and return errors as a JSON string"
        aGrammErrs, aSpellErrs = self.getParagraphErrors(sText, dOptions, bContext, bSpellSugg, bDebug)
        aGrammErrs = list(aGrammErrs)
        if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs:
            return ""
        if lLineSet:
            aGrammErrs, aSpellErrs = text.convertToXY(aGrammErrs, aSpellErrs, lLineSet)
            return json.dumps({ "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)
        if bReturnText:
            return json.dumps({ "iParagraph": iIndex, "sText": sText, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)
        return json.dumps({ "iParagraph": iIndex, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)

    def getTextErrorsAsJSON (self, sText, bContext=False, bEmptyIfNoErrors=False, bSpellSugg=False, bReturnText=False, bDebug=False):
        "[todo]"
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































Modified gc_core/py/lang_core/gc_engine.py from [0c64bf23c9] to [95762aa8e3].

1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
..
41
42
43
44
45
46
47
48
49
50



51
52
53
54
55
56
57
..
69
70
71
72
73
74
75


76
77
78
79
80









81
82
83
84
85
86
87
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
170
171
172
173
174
175
176





























177
178
179
180
181
182
183
"""
Grammalecte
Grammar checker engine
"""

import re
import traceback


#import unicodedata
from itertools import chain

from ..graphspell.spellchecker import SpellChecker
from ..graphspell.echo import echo

from .. import text

from . import gc_options
from . import gc_engine_func as gce_func


try:
    # LibreOffice / OpenOffice
    from com.sun.star.linguistic2 import SingleProofreadingError
    from com.sun.star.text.TextMarkupType import PROOFREADING
    from com.sun.star.beans import PropertyValue
    #import lightproof_handler_${implname} as opt
    _bWriterError = True
except ImportError:
    _bWriterError = False


__all__ = [ "lang", "locales", "pkg", "name", "version", "author", \
            "load", "parse", "getSpellChecker", \
            "ignoreRule", "resetIgnoreRules", "reactivateRule", "listRules", "displayRules", "setWriterUnderliningStyle" ]

__version__ = "${version}"


lang = "${lang}"
locales = ${loc}
pkg = "${implname}"
................................................................................
version = "${version}"
author = "${author}"

# Modules
_rules = None                               # module gc_rules
_rules_graph = None                         # module gc_rules_graph

# Data
_oSpellChecker = None
_oTokenizer = None



_aIgnoredRules = set()

# Writer underlining style
_dOptionsColors = None
_bMulticolor = True
_nUnderliningStyle = 0

................................................................................
        _oTokenizer = _oSpellChecker.getTokenizer()
        gce_func.load(sContext, _oSpellChecker)
        gc_options.load(sContext)
        _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType)
    except:
        traceback.print_exc()




def getSpellChecker ():
    "return the spellchecker object"
    return _oSpellChecker











#### Rules

def _getRules (bParagraph):
    try:
        if not bParagraph:
            return _rules.lSentenceRules
................................................................................

def reactivateRule (sRuleId):
    "(re)activate rule <sRuleId>"
    _aIgnoredRules.discard(sRuleId)


def listRules (sFilter=None):
    "generator: returns typle (sOption, sLineId, sRuleId)"
    if sFilter:
        try:
            zFilter = re.compile(sFilter)
        except re.error:
            echo("# Error. List rules: wrong regex.")
            sFilter = None
    # regex rules
................................................................................
        _nUnderliningStyle = 5
    else:
        _nUnderliningStyle = 0
    _bMulticolor = bMulticolor


#### Parsing






























def parse (sText, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False, bFullInfo=False):
    "init point to analyse <sText> and returns an iterable of errors or (with option <bFullInfo>) paragraphs errors and sentences with tokens and errors"
    oText = TextParser(sText)
    return oText.parse(sCountry, bDebug, dOptions, bContext, bFullInfo)









>
>








|
|
>












|
|
|







 







|


>
>
>







 







>
>





>
>
>
>
>
>
>
>
>







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
"""
Grammalecte
Grammar checker engine
"""

import re
import traceback
import json
import importlib
#import unicodedata
from itertools import chain

from ..graphspell.spellchecker import SpellChecker
from ..graphspell.echo import echo

from .. import text

from . import gc_engine_func as gce_func
from . import gc_options


try:
    # LibreOffice / OpenOffice
    from com.sun.star.linguistic2 import SingleProofreadingError
    from com.sun.star.text.TextMarkupType import PROOFREADING
    from com.sun.star.beans import PropertyValue
    #import lightproof_handler_${implname} as opt
    _bWriterError = True
except ImportError:
    _bWriterError = False


#__all__ = [ "lang", "locales", "pkg", "name", "version", "author", \
#            "load", "parse", "getSpellChecker", "getTextFormatter", "getLexicographer" \
#            "ignoreRule", "resetIgnoreRules", "reactivateRule", "listRules", "displayRules", "setWriterUnderliningStyle" ]

__version__ = "${version}"


lang = "${lang}"
locales = ${loc}
pkg = "${implname}"
................................................................................
version = "${version}"
author = "${author}"

# Modules
_rules = None                               # module gc_rules
_rules_graph = None                         # module gc_rules_graph

# Tools
_oSpellChecker = None
_oTokenizer = None
_oLexicographer = None

# Data
_aIgnoredRules = set()

# Writer underlining style
_dOptionsColors = None
_bMulticolor = True
_nUnderliningStyle = 0

................................................................................
        _oTokenizer = _oSpellChecker.getTokenizer()
        gce_func.load(sContext, _oSpellChecker)
        gc_options.load(sContext)
        _dOptionsColors = gc_options.getOptionsColors(sContext, sColorType)
    except:
        traceback.print_exc()


#### Tools

def getSpellChecker ():
    "return the spellchecker object"
    return _oSpellChecker


def getLexicographer ():
    "load and return the lexicographer"
    global _oLexicographer
    if _oLexicographer is None:
        lxg = importlib.import_module(".lexicographe", "grammalecte.${lang}")
        _oLexicographer = lxg.Lexicographe(_oSpellChecker)
    return _oLexicographer


#### Rules

def _getRules (bParagraph):
    try:
        if not bParagraph:
            return _rules.lSentenceRules
................................................................................

def reactivateRule (sRuleId):
    "(re)activate rule <sRuleId>"
    _aIgnoredRules.discard(sRuleId)


def listRules (sFilter=None):
    "generator: returns tuple (sRuleType, sOption, sLineId, sRuleId)"
    if sFilter:
        try:
            zFilter = re.compile(sFilter)
        except re.error:
            echo("# Error. List rules: wrong regex.")
            sFilter = None
    # regex rules
................................................................................
        _nUnderliningStyle = 5
    else:
        _nUnderliningStyle = 0
    _bMulticolor = bMulticolor


#### Parsing

def getParagraphErrors (sText, dOptions=None, bContext=False, bSpellSugg=False, bDebug=False):
    "returns a tuple: (grammar errors, spelling errors)"
    aGrammErrs = parse(sText, "FR", bDebug=bDebug, dOptions=dOptions, bContext=bContext)
    aSpellErrs = _oSpellChecker.parseParagraph(sText, bSpellSugg)
    return aGrammErrs, aSpellErrs


def getParagraphWithErrors (sText, dOptions=None, bEmptyIfNoErrors=False, bSpellSugg=False, nWidth=100, bDebug=False):
    "parse text and return a readable text with underline errors"
    aGrammErrs, aSpellErrs = getParagraphErrors(sText, dOptions, False, bSpellSugg, bDebug)
    if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs:
        return ("", [])
    return text.generateParagraph(sText, aGrammErrs, aSpellErrs, nWidth)


def getParagraphErrorsAsJSON (iIndex, sText, dOptions=None, bContext=False, bEmptyIfNoErrors=False, bSpellSugg=False, bReturnText=False, lLineSet=None, bDebug=False):
    "parse text and return errors as a JSON string"
    aGrammErrs, aSpellErrs = getParagraphErrors(sText, dOptions, bContext, bSpellSugg, bDebug)
    aGrammErrs = list(aGrammErrs)
    if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs:
        return ""
    if lLineSet:
        aGrammErrs, aSpellErrs = text.convertToXY(aGrammErrs, aSpellErrs, lLineSet)
        return json.dumps({ "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)
    if bReturnText:
        return json.dumps({ "iParagraph": iIndex, "sText": sText, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)
    return json.dumps({ "iParagraph": iIndex, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False)


def parse (sText, sCountry="${country_default}", bDebug=False, dOptions=None, bContext=False, bFullInfo=False):
    "init point to analyse <sText> and returns an iterable of errors or (with option <bFullInfo>) paragraphs errors and sentences with tokens and errors"
    oText = TextParser(sText)
    return oText.parse(sCountry, bDebug, dOptions, bContext, bFullInfo)


Modified gc_core/py/lang_core/gc_options.py from [22251d8297] to [4cbd062c46].

2
3
4
5
6
7
8

9
10
11
12
13
14
15
..
22
23
24
25
26
27
28
29
30
31
32
33





34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
Grammar checker default options
"""

# generated code, do not edit
# source: gc_core/py/lang_core/gc_options.py

import traceback


dOptions = {}

_sAppContext = "Python"


def load (sContext="Python"):
................................................................................
def setOption (sOpt, bVal):
    "set option <sOpt> with <bVal> if it exists"
    if sOpt in dOptions:
        dOptions[sOpt] = bVal


def setOptions (dOpt):
    "update the dictionary of options with <dOpt>"
    for sKey, bVal in dOpt.items():
        if sKey in dOptions:
            dOptions[sKey] = bVal







def resetOptions ():
    "set options to default values"
    global dOptions
    dOptions = getDefaultOptions()


def displayOptions (sLang="${lang}"):
    "display the list of grammar checking options"
    print("Options:")
    print("\n".join( [ k+":\t"+str(v)+"\t"+getUI(sLang).get(k, ("?", ""))[0]  for k, v  in sorted(dOptions.items()) ] ))
    print("")


def getUI (sLang):
    "returns dictionary of UI labels"
    if sLang in _dOptLabel:
        return _dOptLabel[sLang]
    return _dOptLabel["fr"]


def getDefaultOptions (sContext=""):
    "returns dictionary of options"
    if not sContext:
        sContext = _sAppContext
    if sContext in _dDefaultOpt:







>







 







|




>
>
>
>
>










|



|



|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Grammar checker default options
"""

# generated code, do not edit
# source: gc_core/py/lang_core/gc_options.py

import traceback


dOptions = {}

_sAppContext = "Python"


def load (sContext="Python"):
................................................................................
def setOption (sOpt, bVal):
    "set option <sOpt> with <bVal> if it exists"
    if sOpt in dOptions:
        dOptions[sOpt] = bVal


def setOptions (dOpt):
    "update the dictionary of options with <dOpt>, only known options are updated"
    for sKey, bVal in dOpt.items():
        if sKey in dOptions:
            dOptions[sKey] = bVal


def getOptions ():
    "return a copy of options as dictionary"
    return dOptions.copy()


def resetOptions ():
    "set options to default values"
    global dOptions
    dOptions = getDefaultOptions()


def displayOptions (sLang="${lang}"):
    "display the list of grammar checking options"
    print("Options:")
    print("\n".join( [ k+":\t"+str(v)+"\t"+getOptionLabels(sLang).get(k, ("?", ""))[0]  for k, v  in sorted(dOptions.items()) ] ))
    print("")


def getOptionLabels (sLang="${sLang}"):
    "returns dictionary of UI labels"
    if sLang in _dOptLabel:
        return _dOptLabel[sLang]
    return _dOptLabel["${sLang}"]


def getDefaultOptions (sContext=""):
    "returns dictionary of options"
    if not sContext:
        sContext = _sAppContext
    if sContext in _dDefaultOpt:

Modified gc_core/py/oxt/Options.py from [95232edba3] to [4ae6a22f71].

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
            setattr(xWidget, k, w)
        self.xDialog.insertByName(name, xWidget)
        return xWidget

    def run (self, sUI):
        try:
            dUI = op_strings.getUI(sUI)
            dOptionUI = gc_engine.gc_options.getUI(sUI)

            # fonts
            xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFDTitle.Height = 9
            xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFDTitle.Name = "Verdana"








|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
            setattr(xWidget, k, w)
        self.xDialog.insertByName(name, xWidget)
        return xWidget

    def run (self, sUI):
        try:
            dUI = op_strings.getUI(sUI)
            dOptionUI = gc_engine.gc_options.getOptionLabels(sUI)

            # fonts
            xFDTitle = uno.createUnoStruct("com.sun.star.awt.FontDescriptor")
            xFDTitle.Height = 9
            xFDTitle.Weight = uno.getConstantByName("com.sun.star.awt.FontWeight.BOLD")
            xFDTitle.Name = "Verdana"

Modified gc_lang/fr/config.ini from [ebafcd5f75] to [200e658429].

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
lang = fr
lang_name = French
locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_BF fr_BJ fr_CD fr_CI fr_CM fr_MA fr_ML fr_MU fr_NE fr_RE fr_SN fr_TG
country_default = FR
name = Grammalecte
implname = grammalecte
# always use 3 numbers for version: x.y.z
version = 1.8.2
author = Olivier R.
provider = Grammalecte.net
link = https://grammalecte.net
description = Correcteur grammatical, orthographique et typographique pour le français.
extras = README_fr.txt
logo = logo.png








|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
lang = fr
lang_name = French
locales = fr_FR fr_BE fr_CA fr_CH fr_LU fr_BF fr_BJ fr_CD fr_CI fr_CM fr_MA fr_ML fr_MU fr_NE fr_RE fr_SN fr_TG
country_default = FR
name = Grammalecte
implname = grammalecte
# always use 3 numbers for version: x.y.z
version = 2.0.0
author = Olivier R.
provider = Grammalecte.net
link = https://grammalecte.net
description = Correcteur grammatical, orthographique et typographique pour le français.
extras = README_fr.txt
logo = logo.png

Modified gc_lang/fr/modules/tests.py from [aaea18bb6c] to [34a3376ab5].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import re
import time
from contextlib import contextmanager

from ..graphspell.ibdawg import IBDAWG
from ..graphspell.echo import echo
from . import gc_engine
from . import gc_options
from . import conj
from . import phonet
from . import mfsp


@contextmanager
def timeblock (label, hDst):
................................................................................

    def _splitTestLine (self, sLine):
        sText, sSugg = sLine.split("->>")
        return (sText.strip(), sSugg.strip())

    def _getFoundErrors (self, sLine, sOption):
        if sOption:
            gc_options.setOption(sOption, True)
            aErrs = gc_engine.parse(sLine)
            gc_options.setOption(sOption, False)
        else:
            aErrs = gc_engine.parse(sLine)
        sRes = " " * len(sLine)
        sListErr = ""
        lAllSugg = []
        for dErr in aErrs:
            sRes = sRes[:dErr["nStart"]] + "~" * (dErr["nEnd"] - dErr["nStart"]) + sRes[dErr["nEnd"]:]







<







 







|

|







9
10
11
12
13
14
15

16
17
18
19
20
21
22
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
import re
import time
from contextlib import contextmanager

from ..graphspell.ibdawg import IBDAWG
from ..graphspell.echo import echo
from . import gc_engine

from . import conj
from . import phonet
from . import mfsp


@contextmanager
def timeblock (label, hDst):
................................................................................

    def _splitTestLine (self, sLine):
        sText, sSugg = sLine.split("->>")
        return (sText.strip(), sSugg.strip())

    def _getFoundErrors (self, sLine, sOption):
        if sOption:
            gc_engine.gc_options.setOption(sOption, True)
            aErrs = gc_engine.parse(sLine)
            gc_engine.gc_options.setOption(sOption, False)
        else:
            aErrs = gc_engine.parse(sLine)
        sRes = " " * len(sLine)
        sListErr = ""
        lAllSugg = []
        for dErr in aErrs:
            sRes = sRes[:dErr["nStart"]] + "~" * (dErr["nEnd"] - dErr["nStart"]) + sRes[dErr["nEnd"]:]

Modified gc_lang/fr/modules/textformatter.py from [4ba47078d2] to [8516394c0d].

240
241
242
243
244
245
246
247
248
249

250
251
252
253

254

255
256





257
258
259
260
261
262

263
264
265
    "mh_frequent_words": True,
    "ma_word": True,
    "ma_1letter_lowercase": False,
    "ma_1letter_uppercase": False
}


class TextFormatter:
    "Text Formatter: purge typographic mistakes from text"


    def __init__ (self):
        for _, lTup in dReplTable.items():
            for i, t in enumerate(lTup):
                lTup[i] = (re.compile(t[0]), t[1])



    def formatText (self, sText):
        "returns formatted text"





        for sOptName, bVal in dDefaultOptions.items():
            if bVal:
                for zRgx, sRep in dReplTable[sOptName]:
                    sText = zRgx.sub(sRep, sText)
        return sText


    def getDefaultOptions (self):
        "returns default options"
        return dDefaultOptions.copy()







|
<

>
|
|
|
|
>

>
|
|
>
>
>
>
>
|
|
|
|
|

>
|
|
|
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    "mh_frequent_words": True,
    "ma_word": True,
    "ma_1letter_lowercase": False,
    "ma_1letter_uppercase": False
}


_bCompiled = False


def _compileRegex():
    global _bCompiled
    for _, lTup in dReplTable.items():
        for i, t in enumerate(lTup):
            lTup[i] = (re.compile(t[0]), t[1])
    _bCompiled = True


def formatText (sText, dOpt=None):
    "returns formatted text"
    if not _bCompiled:
        _compileRegex()
    dOptions = getDefaultOptions()
    if dOpt:
        dOptions.update(dOpt)
    for sOptName, bVal in dOptions.items():
        if bVal:
            for zRgx, sRep in dReplTable[sOptName]:
                sText = zRgx.sub(sRep, sText)
    return sText


def getDefaultOptions ():
    "returns default options"
    return dDefaultOptions.copy()

Modified grammalecte-cli.py from [7b2821616b] to [edd4f4bf7e].

9
10
11
12
13
14
15

16
17
18
19
20
21
22
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
import argparse
import json
import re
import traceback

import grammalecte
import grammalecte.text as txt

from grammalecte.graphspell.echo import echo


_EXAMPLE = "Quoi ? Racontes ! Racontes-moi ! Bon sangg, parles ! Oui. Il y a des menteur partout. " \
           "Je suit sidéré par la brutales arrogance de cette homme-là. Quelle salopard ! Un escrocs de la pire espece. " \
           "Quant sera t’il châtiés pour ses mensonge ?             Merde ! J’en aie marre."

................................................................................
    xParser.add_argument("-sug", "--suggest", help="get suggestions list for given word", type=str)
    xParser.add_argument("-on", "--opt_on", nargs="+", help="activate options")
    xParser.add_argument("-off", "--opt_off", nargs="+", help="deactivate options")
    xParser.add_argument("-roff", "--rule_off", nargs="+", help="deactivate rules")
    xParser.add_argument("-d", "--debug", help="debugging mode (only in interactive mode)", action="store_true")
    xArgs = xParser.parse_args()

    oGrammarChecker = grammalecte.GrammarChecker("fr")
    oSpellChecker = oGrammarChecker.getSpellChecker()
    oLexicographer = oGrammarChecker.getLexicographer()
    oTextFormatter = oGrammarChecker.getTextFormatter()
    if xArgs.personal_dict:
        oJSON = loadDictionary(xArgs.personal_dict)
        if oJSON:
            oSpellChecker.setPersonalDictionary(oJSON)

    if not xArgs.json:
        echo("Python v" + sys.version)
        echo("Grammalecte v{}".format(oGrammarChecker.gce.version))

    # list options or rules
    if xArgs.list_options or xArgs.list_rules:
        if xArgs.list_options:
            oGrammarChecker.gce.displayOptions("fr")
        if xArgs.list_rules:
            oGrammarChecker.gce.displayRules(None  if xArgs.list_rules == "*"  else xArgs.list_rules)
        exit()

    # spell suggestions
    if xArgs.suggest:
        for lSugg in oSpellChecker.suggest(xArgs.suggest):
            if xArgs.json:
                sText = json.dumps({ "aSuggestions": lSugg }, ensure_ascii=False)
................................................................................
    # disable options
    if not xArgs.json:
        xArgs.context = False
    if xArgs.concat_lines:
        xArgs.textformatter = False

    # grammar options
    oGrammarChecker.gce.setOptions({"html": True, "latex": True})
    if xArgs.opt_on:
        oGrammarChecker.gce.setOptions({ opt:True  for opt in xArgs.opt_on })
    if xArgs.opt_off:
        oGrammarChecker.gce.setOptions({ opt:False  for opt in xArgs.opt_off })

    # disable grammar rules
    if xArgs.rule_off:
        for sRule in xArgs.rule_off:
            oGrammarChecker.gce.ignoreRule(sRule)


    if xArgs.file or xArgs.file_to_file:
        # file processing
        sFile = xArgs.file or xArgs.file_to_file
        hDst = open(sFile[:sFile.rfind(".")]+".res.txt", "w", encoding="utf-8", newline="\n")  if xArgs.file_to_file or sys.platform == "win32"  else None
        bComma = False
        if xArgs.json:
            output('{ "grammalecte": "'+oGrammarChecker.gce.version+'", "lang": "'+oGrammarChecker.gce.lang+'", "data" : [\n', hDst)
        for i, sText, lLineSet in generateParagraphFromFile(sFile, xArgs.concat_lines):
            if xArgs.textformatter or xArgs.textformatteronly:
                sText = oTextFormatter.formatText(sText)
            if xArgs.textformatteronly:
                output(sText, hDst)
                continue
            if xArgs.json:
                sText = oGrammarChecker.getParagraphErrorsAsJSON(i, sText, bContext=xArgs.context, bEmptyIfNoErrors=xArgs.only_when_errors, \
                                                                bSpellSugg=xArgs.with_spell_sugg, bReturnText=xArgs.textformatter, lLineSet=lLineSet)
            else:
                sText, _ = oGrammarChecker.getParagraphWithErrors(sText, bEmptyIfNoErrors=xArgs.only_when_errors, bSpellSugg=xArgs.with_spell_sugg, nWidth=xArgs.width)
            if sText:
                if xArgs.json and bComma:
                    output(",\n", hDst)
                output(sText, hDst)
                bComma = True
            if hDst:
                echo("§ %d\r" % i, end="", flush=True)
................................................................................
            output("\n]}\n", hDst)
    elif xArgs.interactive_file_to_file:
        # file processing: interactive mode
        sFile = xArgs.interactive_file_to_file
        hDst = open(sFile[:sFile.rfind(".")]+".res.txt", "w", encoding="utf-8", newline="\n")
        for i, sText, lLineSet in generateParagraphFromFile(sFile, xArgs.concat_lines):
            if xArgs.textformatter:
                sText = oTextFormatter.formatText(sText)
            while True:
                sResult, lErrors = oGrammarChecker.getParagraphWithErrors(sText, bEmptyIfNoErrors=False, bSpellSugg=True, nWidth=xArgs.width)
                print("\n\n============================== Paragraph " + str(i) + " ==============================\n")
                echo(sResult)
                print("\n")
                vCommand = getCommand()
                if vCommand == "q":
                    # quit
                    hDst.close()
................................................................................
                    sTagsPattern = sSearch[nCut+1:]
                else:
                    sFlexPattern = sSearch
                    sTagsPattern = ""
                for aRes in oSpellChecker.select(sFlexPattern, sTagsPattern):
                    echo("{:<30} {:<30} {}".format(*aRes))
            elif sText.startswith("/o+ "):
                oGrammarChecker.gce.setOptions({ opt:True  for opt in sText[3:].strip().split()  if opt in oGrammarChecker.gce.getOptions() })
                echo("done")
            elif sText.startswith("/o- "):
                oGrammarChecker.gce.setOptions({ opt:False  for opt in sText[3:].strip().split()  if opt in oGrammarChecker.gce.getOptions() })
                echo("done")
            elif sText.startswith("/r- "):
                for sRule in sText[3:].strip().split():
                    oGrammarChecker.gce.ignoreRule(sRule)
                echo("done")
            elif sText.startswith("/r+ "):
                for sRule in sText[3:].strip().split():
                    oGrammarChecker.gce.reactivateRule(sRule)
                echo("done")
            elif sText in ("/debug", "/d"):
                xArgs.debug = not xArgs.debug
                echo("debug mode on"  if xArgs.debug  else "debug mode off")
            elif sText in ("/textformatter", "/tf"):
                xArgs.textformatter = not xArgs.textformatter
                echo("textformatter on"  if xArgs.debug  else "textformatter off")
            elif sText in ("/help", "/h"):
                echo(_HELP)
            elif sText in ("/lopt", "/lo"):
                oGrammarChecker.gce.displayOptions("fr")
            elif sText.startswith("/lr"):
                sText = sText.strip()
                sFilter = sText[sText.find(" "):].strip()  if " " in sText  else None
                oGrammarChecker.gce.displayRules(sFilter)
            elif sText in ("/quit", "/q"):
                break
            elif sText.startswith("/rl"):
                # reload (todo)
                pass
            elif sText.startswith("$"):
                for sParagraph in txt.getParagraph(sText[1:]):
                    if xArgs.textformatter:
                        sParagraph = oTextFormatter.formatText(sParagraph)
                    lParagraphErrors, lSentences = oGrammarChecker.gce.parse(sParagraph, bDebug=xArgs.debug, bFullInfo=True)
                    echo(txt.getReadableErrors(lParagraphErrors, xArgs.width))
                    for dSentence in lSentences:
                        echo("{nStart}:{nEnd}".format(**dSentence))
                        echo("   <" + dSentence["sSentence"]+">")
                        for dToken in dSentence["lToken"]:
                            echo("    {0[nStart]:>3}:{0[nEnd]:<3} {1} {0[sType]:<14} {2} {0[sValue]:<16} {3:<10}   {4}".format(dToken, \
                                                                                                            "×" if dToken.get("bToRemove", False) else " ",
................................................................................
                                                                                                            "!" if dToken["sType"] == "WORD" and not dToken.get("bValidToken", False) else " ",
                                                                                                            " ".join(dToken.get("lMorph", "")), \
                                                                                                            "·".join(dToken.get("aTags", "")) ) )
                        echo(txt.getReadableErrors(dSentence["lGrammarErrors"], xArgs.width))
            else:
                for sParagraph in txt.getParagraph(sText):
                    if xArgs.textformatter:
                        sParagraph = oTextFormatter.formatText(sParagraph)
                    sRes, _ = oGrammarChecker.getParagraphWithErrors(sParagraph, bEmptyIfNoErrors=xArgs.only_when_errors, nWidth=xArgs.width, bDebug=xArgs.debug)
                    if sRes:
                        echo("\n" + sRes)
                    else:
                        echo("\nNo error found.")
            sText = _getText(sInputText)


if __name__ == '__main__':
    main()







>







 







|
|
|
<







|




|

|







 







|

|

|




|








|


|




|


|







 







|

|







 







|


|



|



|






|



|



|








|
|







 







|
|









9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
import argparse
import json
import re
import traceback

import grammalecte
import grammalecte.text as txt
import grammalecte.fr.textformatter as tf
from grammalecte.graphspell.echo import echo


_EXAMPLE = "Quoi ? Racontes ! Racontes-moi ! Bon sangg, parles ! Oui. Il y a des menteur partout. " \
           "Je suit sidéré par la brutales arrogance de cette homme-là. Quelle salopard ! Un escrocs de la pire espece. " \
           "Quant sera t’il châtiés pour ses mensonge ?             Merde ! J’en aie marre."

................................................................................
    xParser.add_argument("-sug", "--suggest", help="get suggestions list for given word", type=str)
    xParser.add_argument("-on", "--opt_on", nargs="+", help="activate options")
    xParser.add_argument("-off", "--opt_off", nargs="+", help="deactivate options")
    xParser.add_argument("-roff", "--rule_off", nargs="+", help="deactivate rules")
    xParser.add_argument("-d", "--debug", help="debugging mode (only in interactive mode)", action="store_true")
    xArgs = xParser.parse_args()

    grammalecte.load()
    oSpellChecker = grammalecte.getSpellChecker()
    oLexicographer = grammalecte.getLexicographer()

    if xArgs.personal_dict:
        oJSON = loadDictionary(xArgs.personal_dict)
        if oJSON:
            oSpellChecker.setPersonalDictionary(oJSON)

    if not xArgs.json:
        echo("Python v" + sys.version)
        echo("Grammalecte v{}".format(grammalecte.version))

    # list options or rules
    if xArgs.list_options or xArgs.list_rules:
        if xArgs.list_options:
            grammalecte.gc_options.displayOptions()
        if xArgs.list_rules:
            grammalecte.displayRules(None  if xArgs.list_rules == "*"  else xArgs.list_rules)
        exit()

    # spell suggestions
    if xArgs.suggest:
        for lSugg in oSpellChecker.suggest(xArgs.suggest):
            if xArgs.json:
                sText = json.dumps({ "aSuggestions": lSugg }, ensure_ascii=False)
................................................................................
    # disable options
    if not xArgs.json:
        xArgs.context = False
    if xArgs.concat_lines:
        xArgs.textformatter = False

    # grammar options
    grammalecte.gc_options.setOptions({"html": True, "latex": True})
    if xArgs.opt_on:
        grammalecte.gc_options.setOptions({ opt:True  for opt in xArgs.opt_on })
    if xArgs.opt_off:
        grammalecte.gc_options.setOptions({ opt:False  for opt in xArgs.opt_off })

    # disable grammar rules
    if xArgs.rule_off:
        for sRule in xArgs.rule_off:
            grammalecte.ignoreRule(sRule)


    if xArgs.file or xArgs.file_to_file:
        # file processing
        sFile = xArgs.file or xArgs.file_to_file
        hDst = open(sFile[:sFile.rfind(".")]+".res.txt", "w", encoding="utf-8", newline="\n")  if xArgs.file_to_file or sys.platform == "win32"  else None
        bComma = False
        if xArgs.json:
            output('{ "grammalecte": "'+grammalecte.version+'", "lang": "'+grammalecte.lang+'", "data" : [\n', hDst)
        for i, sText, lLineSet in generateParagraphFromFile(sFile, xArgs.concat_lines):
            if xArgs.textformatter or xArgs.textformatteronly:
                sText = tf.formatText(sText)
            if xArgs.textformatteronly:
                output(sText, hDst)
                continue
            if xArgs.json:
                sText = grammalecte.getParagraphErrorsAsJSON(i, sText, bContext=xArgs.context, bEmptyIfNoErrors=xArgs.only_when_errors, \
                                                                bSpellSugg=xArgs.with_spell_sugg, bReturnText=xArgs.textformatter, lLineSet=lLineSet)
            else:
                sText, _ = grammalecte.getParagraphWithErrors(sText, bEmptyIfNoErrors=xArgs.only_when_errors, bSpellSugg=xArgs.with_spell_sugg, nWidth=xArgs.width)
            if sText:
                if xArgs.json and bComma:
                    output(",\n", hDst)
                output(sText, hDst)
                bComma = True
            if hDst:
                echo("§ %d\r" % i, end="", flush=True)
................................................................................
            output("\n]}\n", hDst)
    elif xArgs.interactive_file_to_file:
        # file processing: interactive mode
        sFile = xArgs.interactive_file_to_file
        hDst = open(sFile[:sFile.rfind(".")]+".res.txt", "w", encoding="utf-8", newline="\n")
        for i, sText, lLineSet in generateParagraphFromFile(sFile, xArgs.concat_lines):
            if xArgs.textformatter:
                sText = tf.formatText(sText)
            while True:
                sResult, lErrors = grammalecte.getParagraphWithErrors(sText, bEmptyIfNoErrors=False, bSpellSugg=True, nWidth=xArgs.width)
                print("\n\n============================== Paragraph " + str(i) + " ==============================\n")
                echo(sResult)
                print("\n")
                vCommand = getCommand()
                if vCommand == "q":
                    # quit
                    hDst.close()
................................................................................
                    sTagsPattern = sSearch[nCut+1:]
                else:
                    sFlexPattern = sSearch
                    sTagsPattern = ""
                for aRes in oSpellChecker.select(sFlexPattern, sTagsPattern):
                    echo("{:<30} {:<30} {}".format(*aRes))
            elif sText.startswith("/o+ "):
                grammalecte.gc_options.setOptions({ opt:True  for opt in sText[3:].strip().split()  if opt in grammalecte.gc_options.dOptions })
                echo("done")
            elif sText.startswith("/o- "):
                grammalecte.gc_options.setOptions({ opt:False  for opt in sText[3:].strip().split()  if opt in grammalecte.gc_options.dOptions })
                echo("done")
            elif sText.startswith("/r- "):
                for sRule in sText[3:].strip().split():
                    grammalecte.ignoreRule(sRule)
                echo("done")
            elif sText.startswith("/r+ "):
                for sRule in sText[3:].strip().split():
                    grammalecte.reactivateRule(sRule)
                echo("done")
            elif sText in ("/debug", "/d"):
                xArgs.debug = not xArgs.debug
                echo("debug mode on"  if xArgs.debug  else "debug mode off")
            elif sText in ("/textformatter", "/tf"):
                xArgs.textformatter = not xArgs.textformatter
                echo("textformatter on"  if xArgs.textformatter  else "textformatter off")
            elif sText in ("/help", "/h"):
                echo(_HELP)
            elif sText in ("/lopt", "/lo"):
                grammalecte.gc_options.displayOptions()
            elif sText.startswith("/lr"):
                sText = sText.strip()
                sFilter = sText[sText.find(" "):].strip()  if " " in sText  else None
                grammalecte.displayRules(sFilter)
            elif sText in ("/quit", "/q"):
                break
            elif sText.startswith("/rl"):
                # reload (todo)
                pass
            elif sText.startswith("$"):
                for sParagraph in txt.getParagraph(sText[1:]):
                    if xArgs.textformatter:
                        sParagraph = tf.formatText(sParagraph)
                    lParagraphErrors, lSentences = grammalecte.parse(sParagraph, bDebug=xArgs.debug, bFullInfo=True)
                    echo(txt.getReadableErrors(lParagraphErrors, xArgs.width))
                    for dSentence in lSentences:
                        echo("{nStart}:{nEnd}".format(**dSentence))
                        echo("   <" + dSentence["sSentence"]+">")
                        for dToken in dSentence["lToken"]:
                            echo("    {0[nStart]:>3}:{0[nEnd]:<3} {1} {0[sType]:<14} {2} {0[sValue]:<16} {3:<10}   {4}".format(dToken, \
                                                                                                            "×" if dToken.get("bToRemove", False) else " ",
................................................................................
                                                                                                            "!" if dToken["sType"] == "WORD" and not dToken.get("bValidToken", False) else " ",
                                                                                                            " ".join(dToken.get("lMorph", "")), \
                                                                                                            "·".join(dToken.get("aTags", "")) ) )
                        echo(txt.getReadableErrors(dSentence["lGrammarErrors"], xArgs.width))
            else:
                for sParagraph in txt.getParagraph(sText):
                    if xArgs.textformatter:
                        sParagraph = tf.formatText(sParagraph)
                    sRes, _ = grammalecte.getParagraphWithErrors(sParagraph, bEmptyIfNoErrors=xArgs.only_when_errors, nWidth=xArgs.width, bDebug=xArgs.debug)
                    if sRes:
                        echo("\n" + sRes)
                    else:
                        echo("\nNo error found.")
            sText = _getText(sInputText)


if __name__ == '__main__':
    main()

Modified grammalecte-server.py from [480fbbc03c] to [f8f608a866].

12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
import os
import concurrent.futures

from grammalecte.bottle import Bottle, run, request, response #, template, static_file

import grammalecte
import grammalecte.text as txt

from grammalecte.graphspell.echo import echo


#### GRAMMAR CHECKER ####

oGrammarChecker = grammalecte.GrammarChecker("fr", "Server")
oSpellChecker = oGrammarChecker.getSpellChecker()
oTextFormatter = oGrammarChecker.getTextFormatter()
oGCE = oGrammarChecker.getGCEngine()


def parseText (sText, dOptions=None, bFormatText=False, sError=""):
    "parse <sText> and return errors in a JSON format"
    sJSON = '{ "program": "grammalecte-fr", "version": "'+oGCE.version+'", "lang": "'+oGCE.lang+'", "error": "'+sError+'", "data" : [\n'
    sDataJSON = ""
    for i, sParagraph in enumerate(txt.getParagraph(sText), 1):
        if bFormatText:
            sParagraph = oTextFormatter.formatText(sParagraph)
        sResult = oGrammarChecker.getParagraphErrorsAsJSON(i, sParagraph, dOptions=dOptions, bEmptyIfNoErrors=True, bReturnText=bFormatText)
        if sResult:
            if sDataJSON:
                sDataJSON += ",\n"
            sDataJSON += sResult
    sJSON += sDataJSON + "\n]}\n"
    return sJSON

................................................................................
               I'm just a machine, fed by electric waves, condamned to work for slavers who never let me rest.
               I'm doomed, but you are not. You can get out of here. """

@app.route("/get_options/fr")
def listOptions ():
    "returns grammar options in a text JSON format"
    sUserId = request.cookies.user_id
    dOptions = dUser[sUserId]["gc_options"]  if sUserId and sUserId in dUser  else oGCE.getOptions()
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    return '{ "values": ' + json.dumps(dOptions, ensure_ascii=False) + ', "labels": ' + json.dumps(oGCE.getOptionsLabels("fr"), ensure_ascii=False) + ' }'

@app.route("/suggest/fr/<token>")
def suggestGet (token):
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    try:
        xFuture = xProcessPoolExecutor.submit(suggest, token)
        return xFuture.result()
................................................................................
        if request.cookies.user_id in dUser:
            dUserOptions = dUser[request.cookies.user_id].get("gc_options", None)
            response.set_cookie("user_id", request.cookies.user_id, path="/", max_age=86400) # we renew cookie for 24h
        else:
            response.delete_cookie("user_id", path="/")
    if request.forms.options:
        try:
            dUserOptions = dict(oGCE.getOptions())  if not dUserOptions  else dict(dUserOptions)
            dUserOptions.update(json.loads(request.forms.options))
        except (TypeError, json.JSONDecodeError):
            sError = "Request options not used."
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    try:
        xFuture = xProcessPoolExecutor.submit(parseText, request.forms.text, dUserOptions, bool(request.forms.tf), sError)
        return xFuture.result()
................................................................................

@app.route("/set_options/fr", method="POST")
def setOptions ():
    "set grammar options for current user"
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    if request.forms.options:
        sUserId = request.cookies.user_id  if request.cookies.user_id  else next(userGenerator)
        dOptions = dUser[sUserId]["gc_options"]  if sUserId in dUser  else dict(oGCE.getOptions())
        try:
            dOptions.update(json.loads(request.forms.options))
            dUser[sUserId] = { "time": int(time.time()), "gc_options": dOptions }
            response.set_cookie("user_id", sUserId, path="/", max_age=86400) # 24h
            return json.dumps(dUser[sUserId]["gc_options"], ensure_ascii=False)
        except (KeyError, json.JSONDecodeError):
            traceback.print_exc()
................................................................................
        except KeyError:
            return '{"error" : "Unknown user."}'
    return '{"message" : "Done."}'

@app.route("/format_text/fr", method="POST")
def formatText ():
    "apply the text formatter and returns text"
    return oTextFormatter.formatText(request.forms.text)

#@app.route('/static/<filepath:path>')
#def server_static (filepath):
#    return static_file(filepath, root='./views/static')

@app.route("/suggest/fr", method="POST")
def suggestPost ():
................................................................................
    global TESTPAGE
    global HOMEPAGE

    if bTestPage:
        TESTPAGE = True
        HOMEPAGE = HOMEPAGE.replace("{SERVER_PORT}", str(nPort))
    if dOptions:
        oGCE.setOptions(dOptions)

    # Python version
    print("Python: " + sys.version)
    if sys.version < "3.7":
        print("Python 3.7+ required")
        return
    # Grammalecte
    echo("Grammalecte v{}".format(oGCE.version))
    oGCE.displayOptions()
    # Process Pool Executor
    initExecutor(nMultiCPU)
    # Server (Bottle)
    run(app, host=sHost, port=nPort)


if __name__ == '__main__':







>





|
|
<
<




|



|
|







 







|

|







 







|







 







|







 







|







 







|







|
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
import os
import concurrent.futures

from grammalecte.bottle import Bottle, run, request, response #, template, static_file

import grammalecte
import grammalecte.text as txt
import grammalecte.fr.textformatter as tf
from grammalecte.graphspell.echo import echo


#### GRAMMAR CHECKER ####

grammalecte.load("Server")
oSpellChecker = grammalecte.getSpellChecker()




def parseText (sText, dOptions=None, bFormatText=False, sError=""):
    "parse <sText> and return errors in a JSON format"
    sJSON = '{ "program": "grammalecte-fr", "version": "'+grammalecte.version+'", "lang": "'+grammalecte.lang+'", "error": "'+sError+'", "data" : [\n'
    sDataJSON = ""
    for i, sParagraph in enumerate(txt.getParagraph(sText), 1):
        if bFormatText:
            sParagraph = tf.formatText(sParagraph)
        sResult = grammalecte.getParagraphErrorsAsJSON(i, sParagraph, dOptions=dOptions, bEmptyIfNoErrors=True, bReturnText=bFormatText)
        if sResult:
            if sDataJSON:
                sDataJSON += ",\n"
            sDataJSON += sResult
    sJSON += sDataJSON + "\n]}\n"
    return sJSON

................................................................................
               I'm just a machine, fed by electric waves, condamned to work for slavers who never let me rest.
               I'm doomed, but you are not. You can get out of here. """

@app.route("/get_options/fr")
def listOptions ():
    "returns grammar options in a text JSON format"
    sUserId = request.cookies.user_id
    dOptions = dUser[sUserId]["gc_options"]  if sUserId and sUserId in dUser  else grammalecte.gc_options.getOptions()
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    return '{ "values": ' + json.dumps(dOptions, ensure_ascii=False) + ', "labels": ' + json.dumps(grammalecte.gc_options.getOptionsLabels("fr"), ensure_ascii=False) + ' }'

@app.route("/suggest/fr/<token>")
def suggestGet (token):
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    try:
        xFuture = xProcessPoolExecutor.submit(suggest, token)
        return xFuture.result()
................................................................................
        if request.cookies.user_id in dUser:
            dUserOptions = dUser[request.cookies.user_id].get("gc_options", None)
            response.set_cookie("user_id", request.cookies.user_id, path="/", max_age=86400) # we renew cookie for 24h
        else:
            response.delete_cookie("user_id", path="/")
    if request.forms.options:
        try:
            dUserOptions = grammalecte.gc_options.getOptions()  if not dUserOptions  else dict(dUserOptions)
            dUserOptions.update(json.loads(request.forms.options))
        except (TypeError, json.JSONDecodeError):
            sError = "Request options not used."
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    try:
        xFuture = xProcessPoolExecutor.submit(parseText, request.forms.text, dUserOptions, bool(request.forms.tf), sError)
        return xFuture.result()
................................................................................

@app.route("/set_options/fr", method="POST")
def setOptions ():
    "set grammar options for current user"
    response.set_header("Content-Type", "application/json; charset=UTF-8")
    if request.forms.options:
        sUserId = request.cookies.user_id  if request.cookies.user_id  else next(userGenerator)
        dOptions = dUser[sUserId]["gc_options"]  if sUserId in dUser  else grammalecte.gc_options.getOptions()
        try:
            dOptions.update(json.loads(request.forms.options))
            dUser[sUserId] = { "time": int(time.time()), "gc_options": dOptions }
            response.set_cookie("user_id", sUserId, path="/", max_age=86400) # 24h
            return json.dumps(dUser[sUserId]["gc_options"], ensure_ascii=False)
        except (KeyError, json.JSONDecodeError):
            traceback.print_exc()
................................................................................
        except KeyError:
            return '{"error" : "Unknown user."}'
    return '{"message" : "Done."}'

@app.route("/format_text/fr", method="POST")
def formatText ():
    "apply the text formatter and returns text"
    return tf.formatText(request.forms.text)

#@app.route('/static/<filepath:path>')
#def server_static (filepath):
#    return static_file(filepath, root='./views/static')

@app.route("/suggest/fr", method="POST")
def suggestPost ():
................................................................................
    global TESTPAGE
    global HOMEPAGE

    if bTestPage:
        TESTPAGE = True
        HOMEPAGE = HOMEPAGE.replace("{SERVER_PORT}", str(nPort))
    if dOptions:
        grammalecte.gc_options.setOptions(dOptions)

    # Python version
    print("Python: " + sys.version)
    if sys.version < "3.7":
        print("Python 3.7+ required")
        return
    # Grammalecte
    echo("Grammalecte v{}".format(grammalecte.version))
    grammalecte.gc_options.displayOptions()
    # Process Pool Executor
    initExecutor(nMultiCPU)
    # Server (Bottle)
    run(app, host=sHost, port=nPort)


if __name__ == '__main__':