#!/usr/bin/env python3 """ Grammalecte server: grammar checker """ import sys import argparse import json import traceback import time from grammalecte.bottle import Bottle, run, request, response #, template, static_file import grammalecte import grammalecte.text as txt from grammalecte.graphspell.echo import echo HOMEPAGE = """

Grammalecte · Serveur

INFORMATIONS

Analyser du texte

[adresse_serveur]:{SERVER_PORT}/gc_text/fr (POST)

Paramètres :

Lister les options

[adresse_serveur]:{SERVER_PORT}/get_options/fr (GET)

Définir ses options

[adresse_serveur]:{SERVER_PORT}/set_options/fr (POST)

Les options seront enregistrées et réutilisées pour toute requête envoyée avec le cookie comportant l’identifiant attribué.

Paramètres :

Remise à zéro de ses options

[adresse_serveur]:{SERVER_PORT}/reset_options/fr (POST)

TEST

Analyse

Texte à analyser :

(Ces options ne seront prises en compte que pour cette requête.)

Réglages des options

Remise à zéro de ses options

""" SADLIFEOFAMACHINE = """ Lost on the Internet? Yeah... what a sad life we have. You were wandering like a lost soul and you arrived here probably by mistake. 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. """ TESTPAGE = False def genUserId (): "generator: returns id as string for users" i = 0 while True: yield str(i) i += 1 app = Bottle() # GET @app.route("/") def mainPage (): "page for testing purpose" if TESTPAGE: return HOMEPAGE #return template("main", {}) return SADLIFEOFAMACHINE @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 dGCOptions return '{ "values": ' + json.dumps(dOptions) + ', "labels": ' + json.dumps(gce.getOptionsLabels("fr"), ensure_ascii=False) + ' }' # POST @app.route("/gc_text/fr", method="POST") def gcText (): "parse text and returns errors in a JSON text format" #if len(lang) != 2 or lang != "fr": # abort(404, "No grammar checker available for lang “" + str(lang) + "”") bComma = False dOptions = None sError = "" if request.cookies.user_id: if request.cookies.user_id in dUser: dOptions = 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: dOptions = dict(dGCOptions) if not dOptions else dict(dOptions) dOptions.update(json.loads(request.forms.options)) except (TypeError, json.JSONDecodeError): sError = "request options not used" sJSON = '{ "program": "grammalecte-fr", "version": "'+gce.version+'", "lang": "'+gce.lang+'", "error": "'+sError+'", "data" : [\n' for i, sText in enumerate(txt.getParagraph(request.forms.text), 1): if bool(request.forms.tf): sText = oTextFormatter.formatText(sText) sText = oGrammarChecker.generateParagraphAsJSON(i, sText, dOptions=dOptions, bEmptyIfNoErrors=True, bReturnText=bool(request.forms.tf)) if sText: if bComma: sJSON += ",\n" sJSON += sText bComma = True sJSON += "\n]}\n" return sJSON @app.route("/set_options/fr", method="POST") def setOptions (): "set grammar options for current user" 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(dGCOptions) 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"]) except (KeyError, json.JSONDecodeError): traceback.print_exc() return '{"error": "options not registered"}' return '{"error": "no options received"}' @app.route("/reset_options/fr", method="POST") def resetOptions (): "default grammar options" if request.cookies.user_id and request.cookies.user_id in dUser: del dUser[request.cookies.user_id] return "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/') #def server_static (filepath): # return static_file(filepath, root='./views/static') def purgeUsers (): "delete user options older than n hours" try: nNowMinusNHours = int(time.time()) - (int(request.forms.hours) * 60 * 60) for nUserId, dValue in dUser.items(): if dValue["time"] < nNowMinusNHours: del dUser[nUserId] return True except KeyError: traceback.print_exc() return False # ERROR @app.error(404) def error404 (error): "404 error page" return 'Error 404.
' + str(error) # initialisation oGrammarChecker = grammalecte.GrammarChecker("fr", "Server") oSpellChecker = oGrammarChecker.getSpellChecker() oLexicographer = oGrammarChecker.getLexicographer() oTextFormatter = oGrammarChecker.getTextFormatter() gce = oGrammarChecker.getGCEngine() dGCOptions = gce.getOptions() dUser = {} userGenerator = genUserId() def main (sHost="localhost", nPort=8080, dOptions=None, bTestPage=False): "start server" global dGCOptions global TESTPAGE global HOMEPAGE if bTestPage: TESTPAGE = True HOMEPAGE = HOMEPAGE.replace("{SERVER_PORT}", str(nPort)) if dOptions: oGrammarChecker.gce.setOptions(dOptions) dGCOptions = gce.getOptions() print("Python: " + sys.version) echo("Grammalecte v{}".format(gce.version)) echo("Grammar options:\n" + " | ".join([ k + ": " + str(v) for k, v in sorted(dGCOptions.items()) ])) run(app, host=sHost, port=nPort) if __name__ == '__main__': xParser = argparse.ArgumentParser() #xParser.add_argument("lang", type=str, nargs='+', help="lang project to generate (name of folder in /lang)") xParser.add_argument("-ht", "--host", help="host (default: localhost)", type=str) xParser.add_argument("-p", "--port", help="port (default: 8080)", type=int) xParser.add_argument("-t", "--test_page", help="page to test the server on /", action="store_true") xParser.add_argument("-on", "--opt_on", nargs="+", help="activate options") xParser.add_argument("-off", "--opt_off", nargs="+", help="deactivate options") xArgs = xParser.parse_args() dOpt = None if xArgs.opt_on or xArgs.opt_off: dOpt = {} if xArgs.opt_on: dOpt = { opt:True for opt in xArgs.opt_on } if xArgs.opt_off: dOpt.update({ opt:False for opt in xArgs.opt_off }) main(xArgs.host or "localhost", \ xArgs.port or 8080, \ dOpt, xArgs.test_page)