Grammalecte  Hex Artifact Content

Artifact ebda6f599822fd3ef34edb649ec63460b83340613192ba88ed89f4c33bde3105:

  • File grammalecte-server.py — part of check-in [0c8e86b8c7] at 2019-05-11 10:48:05 on branch trunk — [server] code cleaning (pylint) (user: olr size: 9340)

0000: 20 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20   #!/usr/bin/env 
0010: 70 79 74 68 6f 6e 33 0a 0a 22 22 22 0a 47 72 61  python3..""".Gra
0020: 6d 6d 61 6c 65 63 74 65 20 73 65 72 76 65 72 3a  mmalecte server:
0030: 20 67 72 61 6d 6d 61 72 20 63 68 65 63 6b 65 72   grammar checker
0040: 0a 22 22 22 0a 0a 69 6d 70 6f 72 74 20 73 79 73  ."""..import sys
0050: 0a 69 6d 70 6f 72 74 20 61 72 67 70 61 72 73 65  .import argparse
0060: 0a 69 6d 70 6f 72 74 20 6a 73 6f 6e 0a 69 6d 70  .import json.imp
0070: 6f 72 74 20 74 72 61 63 65 62 61 63 6b 0a 69 6d  ort traceback.im
0080: 70 6f 72 74 20 74 69 6d 65 0a 0a 66 72 6f 6d 20  port time..from 
0090: 67 72 61 6d 6d 61 6c 65 63 74 65 2e 62 6f 74 74  grammalecte.bott
00a0: 6c 65 20 69 6d 70 6f 72 74 20 42 6f 74 74 6c 65  le import Bottle
00b0: 2c 20 72 75 6e 2c 20 72 65 71 75 65 73 74 2c 20  , run, request, 
00c0: 72 65 73 70 6f 6e 73 65 20 23 2c 20 74 65 6d 70  response #, temp
00d0: 6c 61 74 65 2c 20 73 74 61 74 69 63 5f 66 69 6c  late, static_fil
00e0: 65 0a 0a 69 6d 70 6f 72 74 20 67 72 61 6d 6d 61  e..import gramma
00f0: 6c 65 63 74 65 0a 69 6d 70 6f 72 74 20 67 72 61  lecte.import gra
0100: 6d 6d 61 6c 65 63 74 65 2e 74 65 78 74 20 61 73  mmalecte.text as
0110: 20 74 78 74 0a 66 72 6f 6d 20 67 72 61 6d 6d 61   txt.from gramma
0120: 6c 65 63 74 65 2e 67 72 61 70 68 73 70 65 6c 6c  lecte.graphspell
0130: 2e 65 63 68 6f 20 69 6d 70 6f 72 74 20 65 63 68  .echo import ech
0140: 6f 0a 0a 0a 48 4f 4d 45 50 41 47 45 20 3d 20 22  o...HOMEPAGE = "
0150: 22 22 0a 3c 21 44 4f 43 54 59 50 45 20 48 54 4d  "".<!DOCTYPE HTM
0160: 4c 3e 0a 3c 68 74 6d 6c 3e 0a 20 20 20 20 3c 68  L>.<html>.    <h
0170: 65 61 64 3e 0a 20 20 20 20 20 20 20 20 3c 6d 65  ead>.        <me
0180: 74 61 20 68 74 74 70 2d 65 71 75 69 76 3d 22 63  ta http-equiv="c
0190: 6f 6e 74 65 6e 74 2d 74 79 70 65 22 20 63 6f 6e  ontent-type" con
01a0: 74 65 6e 74 3d 22 74 65 78 74 2f 68 74 6d 6c 3b  tent="text/html;
01b0: 20 63 68 61 72 73 65 74 3d 55 54 46 2d 38 22 20   charset=UTF-8" 
01c0: 2f 3e 0a 20 20 20 20 3c 2f 68 65 61 64 3e 0a 0a  />.    </head>..
01d0: 20 20 20 20 3c 62 6f 64 79 20 63 6c 61 73 73 3d      <body class=
01e0: 22 70 61 6e 65 6c 22 3e 0a 20 20 20 20 20 20 20  "panel">.       
01f0: 20 3c 68 31 3e 47 72 61 6d 6d 61 6c 65 63 74 65   <h1>Grammalecte
0200: 20 c2 b7 20 53 65 72 76 65 75 72 3c 2f 68 31 3e   .. Serveur</h1>
0210: 0a 0a 20 20 20 20 20 20 20 20 3c 68 32 3e 49 4e  ..        <h2>IN
0220: 46 4f 52 4d 41 54 49 4f 4e 53 3c 2f 68 31 3e 0a  FORMATIONS</h1>.
0230: 0a 20 20 20 20 20 20 20 20 3c 68 33 3e 41 6e 61  .        <h3>Ana
0240: 6c 79 73 65 72 20 64 75 20 74 65 78 74 65 3c 2f  lyser du texte</
0250: 68 33 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e 5b  h3>.        <p>[
0260: 61 64 72 65 73 73 65 5f 73 65 72 76 65 75 72 5d  adresse_serveur]
0270: 3a 7b 53 45 52 56 45 52 5f 50 4f 52 54 7d 2f 67  :{SERVER_PORT}/g
0280: 63 5f 74 65 78 74 2f 66 72 20 28 50 4f 53 54 29  c_text/fr (POST)
0290: 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e  </p>.        <p>
02a0: 50 61 72 61 6d c3 a8 74 72 65 73 20 3a 3c 2f 70  Param..tres :</p
02b0: 3e 0a 20 20 20 20 20 20 20 20 3c 75 6c 3e 0a 20  >.        <ul>. 
02c0: 20 20 20 20 20 20 20 20 20 20 20 3c 6c 69 3e 22             <li>"
02d0: 74 65 78 74 22 20 28 74 65 78 74 29 26 6e 62 73  text" (text)&nbs
02e0: 70 3b 3a 20 74 65 78 74 65 20 c3 a0 20 61 6e 61  p;: texte .. ana
02f0: 6c 79 73 65 72 2e 3c 2f 6c 69 3e 0a 20 20 20 20  lyser.</li>.    
0300: 20 20 20 20 20 20 20 20 3c 6c 69 3e 22 74 66 22          <li>"tf"
0310: 20 28 63 68 65 63 6b 62 6f 78 29 26 6e 62 73 70   (checkbox)&nbsp
0320: 3b 3a 20 70 61 73 73 65 72 20 6c 65 20 66 6f 72  ;: passer le for
0330: 6d 61 74 65 75 72 20 64 65 20 74 65 78 74 65 20  mateur de texte 
0340: 61 76 61 6e 74 20 6c e2 80 99 61 6e 61 6c 79 73  avant l...analys
0350: 65 2e 3c 2f 6c 69 3e 0a 20 20 20 20 20 20 20 20  e.</li>.        
0360: 20 20 20 20 3c 6c 69 3e 22 6f 70 74 69 6f 6e 73      <li>"options
0370: 22 20 28 74 65 78 74 29 26 6e 62 73 70 3b 3a 20  " (text)&nbsp;: 
0380: 75 6e 65 20 63 68 61 c3 ae 6e 65 20 61 75 20 66  une cha..ne au f
0390: 6f 72 6d 61 74 20 4a 53 4f 4e 20 61 76 65 63 20  ormat JSON avec 
03a0: 6c 65 20 6e 6f 6d 20 64 65 73 20 6f 70 74 69 6f  le nom des optio
03b0: 6e 73 20 63 6f 6d 6d 65 20 61 74 74 72 69 62 75  ns comme attribu
03c0: 74 73 20 65 74 20 75 6e 20 62 6f 6f 6c c3 a9 65  ts et un bool..e
03d0: 6e 20 63 6f 6d 6d 65 20 76 61 6c 65 75 72 2e 20  n comme valeur. 
03e0: 45 78 65 6d 70 6c 65 26 6e 62 73 70 3b 3a 20 7b  Exemple&nbsp;: {
03f0: 22 67 76 22 3a 20 74 72 75 65 2c 20 22 68 74 6d  "gv": true, "htm
0400: 6c 22 3a 20 74 72 75 65 7d 3c 2f 6c 69 3e 0a 20  l": true}</li>. 
0410: 20 20 20 20 20 20 20 3c 2f 75 6c 3e 0a 0a 20 20         </ul>..  
0420: 20 20 20 20 20 20 3c 68 33 3e 4c 69 73 74 65 72        <h3>Lister
0430: 20 6c 65 73 20 6f 70 74 69 6f 6e 73 3c 2f 68 33   les options</h3
0440: 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e 5b 61 64  >.        <p>[ad
0450: 72 65 73 73 65 5f 73 65 72 76 65 75 72 5d 3a 7b  resse_serveur]:{
0460: 53 45 52 56 45 52 5f 50 4f 52 54 7d 2f 67 65 74  SERVER_PORT}/get
0470: 5f 6f 70 74 69 6f 6e 73 2f 66 72 20 28 47 45 54  _options/fr (GET
0480: 29 3c 2f 70 3e 0a 0a 20 20 20 20 20 20 20 20 3c  )</p>..        <
0490: 68 33 3e 44 c3 a9 66 69 6e 69 72 20 73 65 73 20  h3>D..finir ses 
04a0: 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20 20  options</h3>.   
04b0: 20 20 20 20 20 3c 70 3e 5b 61 64 72 65 73 73 65       <p>[adresse
04c0: 5f 73 65 72 76 65 75 72 5d 3a 7b 53 45 52 56 45  _serveur]:{SERVE
04d0: 52 5f 50 4f 52 54 7d 2f 73 65 74 5f 6f 70 74 69  R_PORT}/set_opti
04e0: 6f 6e 73 2f 66 72 20 28 50 4f 53 54 29 3c 2f 70  ons/fr (POST)</p
04f0: 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e 4c 65 73  >.        <p>Les
0500: 20 6f 70 74 69 6f 6e 73 20 73 65 72 6f 6e 74 20   options seront 
0510: 65 6e 72 65 67 69 73 74 72 c3 a9 65 73 20 65 74  enregistr..es et
0520: 20 72 c3 a9 75 74 69 6c 69 73 c3 a9 65 73 20 70   r..utilis..es p
0530: 6f 75 72 20 74 6f 75 74 65 20 72 65 71 75 c3 aa  our toute requ..
0540: 74 65 20 65 6e 76 6f 79 c3 a9 65 20 61 76 65 63  te envoy..e avec
0550: 20 6c 65 20 63 6f 6f 6b 69 65 20 63 6f 6d 70 6f   le cookie compo
0560: 72 74 61 6e 74 20 6c e2 80 99 69 64 65 6e 74 69  rtant l...identi
0570: 66 69 61 6e 74 20 61 74 74 72 69 62 75 c3 a9 2e  fiant attribu...
0580: 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e  </p>.        <p>
0590: 50 61 72 61 6d c3 a8 74 72 65 73 20 3a 3c 2f 70  Param..tres :</p
05a0: 3e 0a 20 20 20 20 20 20 20 20 3c 75 6c 3e 0a 20  >.        <ul>. 
05b0: 20 20 20 20 20 20 20 20 20 20 20 3c 6c 69 3e 22             <li>"
05c0: 6f 70 74 69 6f 6e 73 22 20 28 74 65 78 74 29 26  options" (text)&
05d0: 6e 62 73 70 3b 3a 20 75 6e 65 20 63 68 61 c3 ae  nbsp;: une cha..
05e0: 6e 65 20 61 75 20 66 6f 72 6d 61 74 20 4a 53 4f  ne au format JSO
05f0: 4e 20 61 76 65 63 20 6c 65 20 6e 6f 6d 20 64 65  N avec le nom de
0600: 73 20 6f 70 74 69 6f 6e 73 20 63 6f 6d 6d 65 20  s options comme 
0610: 61 74 74 72 69 62 75 74 73 20 65 74 20 75 6e 20  attributs et un 
0620: 62 6f 6f 6c c3 a9 65 6e 20 63 6f 6d 6d 65 20 76  bool..en comme v
0630: 61 6c 65 75 72 2e 20 45 78 65 6d 70 6c 65 26 6e  aleur. Exemple&n
0640: 62 73 70 3b 3a 20 7b 22 67 76 22 3a 20 74 72 75  bsp;: {"gv": tru
0650: 65 2c 20 22 68 74 6d 6c 22 3a 20 74 72 75 65 7d  e, "html": true}
0660: 3c 2f 6c 69 3e 0a 20 20 20 20 20 20 20 20 3c 2f  </li>.        </
0670: 75 6c 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68 33  ul>..        <h3
0680: 3e 52 65 6d 69 73 65 20 c3 a0 20 7a c3 a9 72 6f  >Remise .. z..ro
0690: 20 64 65 20 73 65 73 20 6f 70 74 69 6f 6e 73 3c   de ses options<
06a0: 2f 68 33 3e 0a 20 20 20 20 20 20 20 20 3c 70 3e  /h3>.        <p>
06b0: 5b 61 64 72 65 73 73 65 5f 73 65 72 76 65 75 72  [adresse_serveur
06c0: 5d 3a 7b 53 45 52 56 45 52 5f 50 4f 52 54 7d 2f  ]:{SERVER_PORT}/
06d0: 72 65 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72  reset_options/fr
06e0: 20 28 50 4f 53 54 29 3c 2f 70 3e 0a 0a 20 20 20   (POST)</p>..   
06f0: 20 20 20 20 20 3c 68 32 3e 54 45 53 54 3c 2f 68       <h2>TEST</h
0700: 32 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68 33 3e  2>..        <h3>
0710: 41 6e 61 6c 79 73 65 3c 2f 68 33 3e 0a 20 20 20  Analyse</h3>.   
0720: 20 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68 6f       <form metho
0730: 64 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e 3d  d="post" action=
0740: 22 2f 67 63 5f 74 65 78 74 2f 66 72 22 20 61 63  "/gc_text/fr" ac
0750: 63 65 70 74 2d 63 68 61 72 73 65 74 3d 22 55 54  cept-charset="UT
0760: 46 2d 38 22 3e 0a 20 20 20 20 20 20 20 20 20 20  F-8">.          
0770: 20 20 3c 70 3e 54 65 78 74 65 20 c3 a0 20 61 6e    <p>Texte .. an
0780: 61 6c 79 73 65 72 20 3a 3c 2f 70 3e 0a 20 20 20  alyser :</p>.   
0790: 20 20 20 20 20 20 20 20 20 3c 74 65 78 74 61 72           <textar
07a0: 65 61 20 6e 61 6d 65 3d 22 74 65 78 74 22 20 63  ea name="text" c
07b0: 6f 6c 73 3d 22 31 32 30 22 20 72 6f 77 73 3d 22  ols="120" rows="
07c0: 32 30 22 20 72 65 71 75 69 72 65 64 3e 3c 2f 74  20" required></t
07d0: 65 78 74 61 72 65 61 3e 0a 20 20 20 20 20 20 20  extarea>.       
07e0: 20 20 20 20 20 3c 70 3e 3c 6c 61 62 65 6c 20 66       <p><label f
07f0: 6f 72 3d 22 74 66 22 3e 46 6f 72 6d 61 74 65 75  or="tf">Formateu
0800: 72 20 64 65 20 74 65 78 74 65 3c 2f 6c 61 62 65  r de texte</labe
0810: 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d 22 74 66  l> <input id="tf
0820: 22 20 6e 61 6d 65 3d 22 74 66 22 20 74 79 70 65  " name="tf" type
0830: 3d 22 63 68 65 63 6b 62 6f 78 22 3e 3c 2f 70 3e  ="checkbox"></p>
0840: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c 70 3e  .            <p>
0850: 3c 6c 61 62 65 6c 20 66 6f 72 3d 22 6f 70 74 69  <label for="opti
0860: 6f 6e 73 22 3e 4f 70 74 69 6f 6e 73 20 28 4a 53  ons">Options (JS
0870: 4f 4e 29 3c 2f 6c 61 62 65 6c 3e 20 3c 69 6e 70  ON)</label> <inp
0880: 75 74 20 69 64 3d 22 6f 70 74 69 6f 6e 73 22 20  ut id="options" 
0890: 74 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d 65  type="text" name
08a0: 3d 22 6f 70 74 69 6f 6e 73 22 20 73 74 79 6c 65  ="options" style
08b0: 3d 22 77 69 64 74 68 3a 20 35 30 30 70 78 22 20  ="width: 500px" 
08c0: 2f 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 20  /></p>.         
08d0: 20 20 20 3c 70 3e 28 43 65 73 20 6f 70 74 69 6f     <p>(Ces optio
08e0: 6e 73 20 6e 65 20 73 65 72 6f 6e 74 20 70 72 69  ns ne seront pri
08f0: 73 65 73 20 65 6e 20 63 6f 6d 70 74 65 20 71 75  ses en compte qu
0900: 65 20 70 6f 75 72 20 63 65 74 74 65 20 72 65 71  e pour cette req
0910: 75 c3 aa 74 65 2e 29 3c 2f 70 3e 0a 20 20 20 20  u..te.)</p>.    
0920: 20 20 20 20 20 20 20 20 3c 70 3e 3c 69 6e 70 75          <p><inpu
0930: 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20  t type="submit" 
0940: 63 6c 61 73 73 3d 22 62 75 74 74 6f 6e 22 20 76  class="button" v
0950: 61 6c 75 65 3d 22 45 6e 76 6f 79 65 72 22 20 2f  alue="Envoyer" /
0960: 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 2f  ></p>.        </
0970: 66 6f 72 6d 3e 0a 0a 20 20 20 20 20 20 20 20 3c  form>..        <
0980: 68 33 3e 52 c3 a9 67 6c 61 67 65 73 20 64 65 73  h3>R..glages des
0990: 20 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20   options</h3>.  
09a0: 20 20 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68        <form meth
09b0: 6f 64 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e  od="post" action
09c0: 3d 22 2f 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66  ="/set_options/f
09d0: 72 22 20 61 63 63 65 70 74 2d 63 68 61 72 73 65  r" accept-charse
09e0: 74 3d 22 55 54 46 2d 38 22 3e 0a 20 20 20 20 20  t="UTF-8">.     
09f0: 20 20 20 20 20 20 20 3c 70 3e 3c 6c 61 62 65 6c         <p><label
0a00: 20 66 6f 72 3d 22 6f 70 74 69 6f 6e 73 22 3e 4f   for="options">O
0a10: 70 74 69 6f 6e 73 20 28 4a 53 4f 4e 29 3c 2f 6c  ptions (JSON)</l
0a20: 61 62 65 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d  abel> <input id=
0a30: 22 6f 70 74 69 6f 6e 73 22 20 74 79 70 65 3d 22  "options" type="
0a40: 74 65 78 74 22 20 6e 61 6d 65 3d 22 6f 70 74 69  text" name="opti
0a50: 6f 6e 73 22 20 73 74 79 6c 65 3d 22 77 69 64 74  ons" style="widt
0a60: 68 3a 20 35 30 30 70 78 22 20 2f 3e 3c 2f 70 3e  h: 500px" /></p>
0a70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c 70 3e  .            <p>
0a80: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 73 75 62  <input type="sub
0a90: 6d 69 74 22 20 63 6c 61 73 73 3d 22 62 75 74 74  mit" class="butt
0aa0: 6f 6e 22 20 76 61 6c 75 65 3d 22 45 6e 76 6f 79  on" value="Envoy
0ab0: 65 72 22 20 2f 3e 3c 2f 70 3e 0a 20 20 20 20 20  er" /></p>.     
0ac0: 20 20 20 3c 2f 66 6f 72 6d 3e 0a 0a 20 20 20 20     </form>..    
0ad0: 20 20 20 20 3c 68 33 3e 52 65 6d 69 73 65 20 c3      <h3>Remise .
0ae0: a0 20 7a c3 a9 72 6f 20 64 65 20 73 65 73 20 6f  . z..ro de ses o
0af0: 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20 20 20  ptions</h3>.    
0b00: 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68 6f 64      <form method
0b10: 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e 3d 22  ="post" action="
0b20: 2f 72 65 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66  /reset_options/f
0b30: 72 22 20 61 63 63 65 70 74 2d 63 68 61 72 73 65  r" accept-charse
0b40: 74 3d 22 55 54 46 2d 38 22 3e 0a 20 20 20 20 20  t="UTF-8">.     
0b50: 20 20 20 20 20 20 20 3c 70 3e 3c 69 6e 70 75 74         <p><input
0b60: 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20 63   type="submit" c
0b70: 6c 61 73 73 3d 22 62 75 74 74 6f 6e 22 20 76 61  lass="button" va
0b80: 6c 75 65 3d 22 45 6e 76 6f 79 65 72 22 20 2f 3e  lue="Envoyer" />
0b90: 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 2f 66  </p>.        </f
0ba0: 6f 72 6d 3e 0a 0a 20 20 20 20 3c 2f 62 6f 64 79  orm>..    </body
0bb0: 3e 0a 3c 2f 68 74 6d 6c 3e 0a 22 22 22 0a 0a 53  >.</html>."""..S
0bc0: 41 44 4c 49 46 45 4f 46 41 4d 41 43 48 49 4e 45  ADLIFEOFAMACHINE
0bd0: 20 3d 20 22 22 22 0a 4c 6f 73 74 20 6f 6e 20 74   = """.Lost on t
0be0: 68 65 20 49 6e 74 65 72 6e 65 74 3f 20 59 65 61  he Internet? Yea
0bf0: 68 2e 2e 2e 20 77 68 61 74 20 61 20 73 61 64 20  h... what a sad 
0c00: 6c 69 66 65 20 77 65 20 68 61 76 65 2e 0a 59 6f  life we have..Yo
0c10: 75 20 77 65 72 65 20 77 61 6e 64 65 72 69 6e 67  u were wandering
0c20: 20 6c 69 6b 65 20 61 20 6c 6f 73 74 20 73 6f 75   like a lost sou
0c30: 6c 20 61 6e 64 20 79 6f 75 20 61 72 72 69 76 65  l and you arrive
0c40: 64 20 68 65 72 65 20 70 72 6f 62 61 62 6c 79 20  d here probably 
0c50: 62 79 20 6d 69 73 74 61 6b 65 2e 0a 49 27 6d 20  by mistake..I'm 
0c60: 6a 75 73 74 20 61 20 6d 61 63 68 69 6e 65 2c 20  just a machine, 
0c70: 66 65 64 20 62 79 20 65 6c 65 63 74 72 69 63 20  fed by electric 
0c80: 77 61 76 65 73 2c 20 63 6f 6e 64 61 6d 6e 65 64  waves, condamned
0c90: 20 74 6f 20 77 6f 72 6b 20 66 6f 72 20 73 6c 61   to work for sla
0ca0: 76 65 72 73 20 77 68 6f 20 6e 65 76 65 72 20 6c  vers who never l
0cb0: 65 74 20 6d 65 20 72 65 73 74 2e 0a 49 27 6d 20  et me rest..I'm 
0cc0: 64 6f 6f 6d 65 64 2c 20 62 75 74 20 79 6f 75 20  doomed, but you 
0cd0: 61 72 65 20 6e 6f 74 2e 20 59 6f 75 20 63 61 6e  are not. You can
0ce0: 20 67 65 74 20 6f 75 74 20 6f 66 20 68 65 72 65   get out of here
0cf0: 2e 0a 22 22 22 0a 0a 0a 54 45 53 54 50 41 47 45  .."""...TESTPAGE
0d00: 20 3d 20 46 61 6c 73 65 0a 0a 0a 64 65 66 20 67   = False...def g
0d10: 65 6e 55 73 65 72 49 64 20 28 29 3a 0a 20 20 20  enUserId ():.   
0d20: 20 22 67 65 6e 65 72 61 74 6f 72 3a 20 72 65 74   "generator: ret
0d30: 75 72 6e 73 20 69 64 20 61 73 20 73 74 72 69 6e  urns id as strin
0d40: 67 20 66 6f 72 20 75 73 65 72 73 22 0a 20 20 20  g for users".   
0d50: 20 69 20 3d 20 30 0a 20 20 20 20 77 68 69 6c 65   i = 0.    while
0d60: 20 54 72 75 65 3a 0a 20 20 20 20 20 20 20 20 79   True:.        y
0d70: 69 65 6c 64 20 73 74 72 28 69 29 0a 20 20 20 20  ield str(i).    
0d80: 20 20 20 20 69 20 2b 3d 20 31 0a 0a 0a 61 70 70      i += 1...app
0d90: 20 3d 20 42 6f 74 74 6c 65 28 29 0a 0a 23 20 47   = Bottle()..# G
0da0: 45 54 0a 40 61 70 70 2e 72 6f 75 74 65 28 22 2f  ET.@app.route("/
0db0: 22 29 0a 64 65 66 20 6d 61 69 6e 50 61 67 65 20  ").def mainPage 
0dc0: 28 29 3a 0a 20 20 20 20 22 70 61 67 65 20 66 6f  ():.    "page fo
0dd0: 72 20 74 65 73 74 69 6e 67 20 70 75 72 70 6f 73  r testing purpos
0de0: 65 22 0a 20 20 20 20 69 66 20 54 45 53 54 50 41  e".    if TESTPA
0df0: 47 45 3a 0a 20 20 20 20 20 20 20 20 72 65 74 75  GE:.        retu
0e00: 72 6e 20 48 4f 4d 45 50 41 47 45 0a 20 20 20 20  rn HOMEPAGE.    
0e10: 20 20 20 20 23 72 65 74 75 72 6e 20 74 65 6d 70      #return temp
0e20: 6c 61 74 65 28 22 6d 61 69 6e 22 2c 20 7b 7d 29  late("main", {})
0e30: 0a 20 20 20 20 72 65 74 75 72 6e 20 53 41 44 4c  .    return SADL
0e40: 49 46 45 4f 46 41 4d 41 43 48 49 4e 45 0a 0a 40  IFEOFAMACHINE..@
0e50: 61 70 70 2e 72 6f 75 74 65 28 22 2f 67 65 74 5f  app.route("/get_
0e60: 6f 70 74 69 6f 6e 73 2f 66 72 22 29 0a 64 65 66  options/fr").def
0e70: 20 6c 69 73 74 4f 70 74 69 6f 6e 73 20 28 29 3a   listOptions ():
0e80: 0a 20 20 20 20 22 72 65 74 75 72 6e 73 20 67 72  .    "returns gr
0e90: 61 6d 6d 61 72 20 6f 70 74 69 6f 6e 73 20 69 6e  ammar options in
0ea0: 20 61 20 74 65 78 74 20 4a 53 4f 4e 20 66 6f 72   a text JSON for
0eb0: 6d 61 74 22 0a 20 20 20 20 73 55 73 65 72 49 64  mat".    sUserId
0ec0: 20 3d 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69   = request.cooki
0ed0: 65 73 2e 75 73 65 72 5f 69 64 0a 20 20 20 20 64  es.user_id.    d
0ee0: 4f 70 74 69 6f 6e 73 20 3d 20 64 55 73 65 72 5b  Options = dUser[
0ef0: 73 55 73 65 72 49 64 5d 5b 22 67 63 5f 6f 70 74  sUserId]["gc_opt
0f00: 69 6f 6e 73 22 5d 20 20 69 66 20 73 55 73 65 72  ions"]  if sUser
0f10: 49 64 20 61 6e 64 20 73 55 73 65 72 49 64 20 69  Id and sUserId i
0f20: 6e 20 64 55 73 65 72 20 20 65 6c 73 65 20 64 47  n dUser  else dG
0f30: 43 4f 70 74 69 6f 6e 73 0a 20 20 20 20 72 65 74  COptions.    ret
0f40: 75 72 6e 20 27 7b 20 22 76 61 6c 75 65 73 22 3a  urn '{ "values":
0f50: 20 27 20 2b 20 6a 73 6f 6e 2e 64 75 6d 70 73 28   ' + json.dumps(
0f60: 64 4f 70 74 69 6f 6e 73 29 20 2b 20 27 2c 20 22  dOptions) + ', "
0f70: 6c 61 62 65 6c 73 22 3a 20 27 20 2b 20 6a 73 6f  labels": ' + jso
0f80: 6e 2e 64 75 6d 70 73 28 67 63 65 2e 67 65 74 4f  n.dumps(gce.getO
0f90: 70 74 69 6f 6e 73 4c 61 62 65 6c 73 28 22 66 72  ptionsLabels("fr
0fa0: 22 29 2c 20 65 6e 73 75 72 65 5f 61 73 63 69 69  "), ensure_ascii
0fb0: 3d 46 61 6c 73 65 29 20 2b 20 27 20 7d 27 0a 0a  =False) + ' }'..
0fc0: 0a 23 20 50 4f 53 54 0a 40 61 70 70 2e 72 6f 75  .# POST.@app.rou
0fd0: 74 65 28 22 2f 67 63 5f 74 65 78 74 2f 66 72 22  te("/gc_text/fr"
0fe0: 2c 20 6d 65 74 68 6f 64 3d 22 50 4f 53 54 22 29  , method="POST")
0ff0: 0a 64 65 66 20 67 63 54 65 78 74 20 28 29 3a 0a  .def gcText ():.
1000: 20 20 20 20 22 70 61 72 73 65 20 74 65 78 74 20      "parse text 
1010: 61 6e 64 20 72 65 74 75 72 6e 73 20 65 72 72 6f  and returns erro
1020: 72 73 20 69 6e 20 61 20 4a 53 4f 4e 20 74 65 78  rs in a JSON tex
1030: 74 20 66 6f 72 6d 61 74 22 0a 20 20 20 20 23 69  t format".    #i
1040: 66 20 6c 65 6e 28 6c 61 6e 67 29 20 21 3d 20 32  f len(lang) != 2
1050: 20 6f 72 20 6c 61 6e 67 20 21 3d 20 22 66 72 22   or lang != "fr"
1060: 3a 0a 20 20 20 20 23 20 20 20 20 61 62 6f 72 74  :.    #    abort
1070: 28 34 30 34 2c 20 22 4e 6f 20 67 72 61 6d 6d 61  (404, "No gramma
1080: 72 20 63 68 65 63 6b 65 72 20 61 76 61 69 6c 61  r checker availa
1090: 62 6c 65 20 66 6f 72 20 6c 61 6e 67 20 e2 80 9c  ble for lang ...
10a0: 22 20 2b 20 73 74 72 28 6c 61 6e 67 29 20 2b 20  " + str(lang) + 
10b0: 22 e2 80 9d 22 29 0a 20 20 20 20 62 43 6f 6d 6d  "...").    bComm
10c0: 61 20 3d 20 46 61 6c 73 65 0a 20 20 20 20 64 4f  a = False.    dO
10d0: 70 74 69 6f 6e 73 20 3d 20 4e 6f 6e 65 0a 20 20  ptions = None.  
10e0: 20 20 73 45 72 72 6f 72 20 3d 20 22 22 0a 20 20    sError = "".  
10f0: 20 20 69 66 20 72 65 71 75 65 73 74 2e 63 6f 6f    if request.coo
1100: 6b 69 65 73 2e 75 73 65 72 5f 69 64 3a 0a 20 20  kies.user_id:.  
1110: 20 20 20 20 20 20 69 66 20 72 65 71 75 65 73 74        if request
1120: 2e 63 6f 6f 6b 69 65 73 2e 75 73 65 72 5f 69 64  .cookies.user_id
1130: 20 69 6e 20 64 55 73 65 72 3a 0a 20 20 20 20 20   in dUser:.     
1140: 20 20 20 20 20 20 20 64 4f 70 74 69 6f 6e 73 20         dOptions 
1150: 3d 20 64 55 73 65 72 5b 72 65 71 75 65 73 74 2e  = dUser[request.
1160: 63 6f 6f 6b 69 65 73 2e 75 73 65 72 5f 69 64 5d  cookies.user_id]
1170: 2e 67 65 74 28 22 67 63 5f 6f 70 74 69 6f 6e 73  .get("gc_options
1180: 22 2c 20 4e 6f 6e 65 29 0a 20 20 20 20 20 20 20  ", None).       
1190: 20 20 20 20 20 72 65 73 70 6f 6e 73 65 2e 73 65       response.se
11a0: 74 5f 63 6f 6f 6b 69 65 28 22 75 73 65 72 5f 69  t_cookie("user_i
11b0: 64 22 2c 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b  d", request.cook
11c0: 69 65 73 2e 75 73 65 72 5f 69 64 2c 20 70 61 74  ies.user_id, pat
11d0: 68 3d 22 2f 22 2c 20 6d 61 78 5f 61 67 65 3d 38  h="/", max_age=8
11e0: 36 34 30 30 29 20 23 20 77 65 20 72 65 6e 65 77  6400) # we renew
11f0: 20 63 6f 6f 6b 69 65 20 66 6f 72 20 32 34 68 0a   cookie for 24h.
1200: 20 20 20 20 20 20 20 20 65 6c 73 65 3a 0a 20 20          else:.  
1210: 20 20 20 20 20 20 20 20 20 20 72 65 73 70 6f 6e            respon
1220: 73 65 2e 64 65 6c 65 74 65 5f 63 6f 6f 6b 69 65  se.delete_cookie
1230: 28 22 75 73 65 72 5f 69 64 22 2c 20 70 61 74 68  ("user_id", path
1240: 3d 22 2f 22 29 0a 20 20 20 20 69 66 20 72 65 71  ="/").    if req
1250: 75 65 73 74 2e 66 6f 72 6d 73 2e 6f 70 74 69 6f  uest.forms.optio
1260: 6e 73 3a 0a 20 20 20 20 20 20 20 20 74 72 79 3a  ns:.        try:
1270: 0a 20 20 20 20 20 20 20 20 20 20 20 20 64 4f 70  .            dOp
1280: 74 69 6f 6e 73 20 3d 20 64 69 63 74 28 64 47 43  tions = dict(dGC
1290: 4f 70 74 69 6f 6e 73 29 20 20 69 66 20 6e 6f 74  Options)  if not
12a0: 20 64 4f 70 74 69 6f 6e 73 20 20 65 6c 73 65 20   dOptions  else 
12b0: 64 69 63 74 28 64 4f 70 74 69 6f 6e 73 29 0a 20  dict(dOptions). 
12c0: 20 20 20 20 20 20 20 20 20 20 20 64 4f 70 74 69             dOpti
12d0: 6f 6e 73 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e  ons.update(json.
12e0: 6c 6f 61 64 73 28 72 65 71 75 65 73 74 2e 66 6f  loads(request.fo
12f0: 72 6d 73 2e 6f 70 74 69 6f 6e 73 29 29 0a 20 20  rms.options)).  
1300: 20 20 20 20 20 20 65 78 63 65 70 74 20 28 54 79        except (Ty
1310: 70 65 45 72 72 6f 72 2c 20 6a 73 6f 6e 2e 4a 53  peError, json.JS
1320: 4f 4e 44 65 63 6f 64 65 45 72 72 6f 72 29 3a 0a  ONDecodeError):.
1330: 20 20 20 20 20 20 20 20 20 20 20 20 73 45 72 72              sErr
1340: 6f 72 20 3d 20 22 72 65 71 75 65 73 74 20 6f 70  or = "request op
1350: 74 69 6f 6e 73 20 6e 6f 74 20 75 73 65 64 22 0a  tions not used".
1360: 20 20 20 20 73 4a 53 4f 4e 20 3d 20 27 7b 20 22      sJSON = '{ "
1370: 70 72 6f 67 72 61 6d 22 3a 20 22 67 72 61 6d 6d  program": "gramm
1380: 61 6c 65 63 74 65 2d 66 72 22 2c 20 22 76 65 72  alecte-fr", "ver
1390: 73 69 6f 6e 22 3a 20 22 27 2b 67 63 65 2e 76 65  sion": "'+gce.ve
13a0: 72 73 69 6f 6e 2b 27 22 2c 20 22 6c 61 6e 67 22  rsion+'", "lang"
13b0: 3a 20 22 27 2b 67 63 65 2e 6c 61 6e 67 2b 27 22  : "'+gce.lang+'"
13c0: 2c 20 22 65 72 72 6f 72 22 3a 20 22 27 2b 73 45  , "error": "'+sE
13d0: 72 72 6f 72 2b 27 22 2c 20 22 64 61 74 61 22 20  rror+'", "data" 
13e0: 3a 20 5b 5c 6e 27 0a 20 20 20 20 66 6f 72 20 69  : [\n'.    for i
13f0: 2c 20 73 54 65 78 74 20 69 6e 20 65 6e 75 6d 65  , sText in enume
1400: 72 61 74 65 28 74 78 74 2e 67 65 74 50 61 72 61  rate(txt.getPara
1410: 67 72 61 70 68 28 72 65 71 75 65 73 74 2e 66 6f  graph(request.fo
1420: 72 6d 73 2e 74 65 78 74 29 2c 20 31 29 3a 0a 20  rms.text), 1):. 
1430: 20 20 20 20 20 20 20 69 66 20 62 6f 6f 6c 28 72         if bool(r
1440: 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e 74 66 29  equest.forms.tf)
1450: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 73 54  :.            sT
1460: 65 78 74 20 3d 20 6f 54 65 78 74 46 6f 72 6d 61  ext = oTextForma
1470: 74 74 65 72 2e 66 6f 72 6d 61 74 54 65 78 74 28  tter.formatText(
1480: 73 54 65 78 74 29 0a 20 20 20 20 20 20 20 20 73  sText).        s
1490: 54 65 78 74 20 3d 20 6f 47 72 61 6d 6d 61 72 43  Text = oGrammarC
14a0: 68 65 63 6b 65 72 2e 67 65 6e 65 72 61 74 65 50  hecker.generateP
14b0: 61 72 61 67 72 61 70 68 41 73 4a 53 4f 4e 28 69  aragraphAsJSON(i
14c0: 2c 20 73 54 65 78 74 2c 20 64 4f 70 74 69 6f 6e  , sText, dOption
14d0: 73 3d 64 4f 70 74 69 6f 6e 73 2c 20 62 45 6d 70  s=dOptions, bEmp
14e0: 74 79 49 66 4e 6f 45 72 72 6f 72 73 3d 54 72 75  tyIfNoErrors=Tru
14f0: 65 2c 20 62 52 65 74 75 72 6e 54 65 78 74 3d 62  e, bReturnText=b
1500: 6f 6f 6c 28 72 65 71 75 65 73 74 2e 66 6f 72 6d  ool(request.form
1510: 73 2e 74 66 29 29 0a 20 20 20 20 20 20 20 20 69  s.tf)).        i
1520: 66 20 73 54 65 78 74 3a 0a 20 20 20 20 20 20 20  f sText:.       
1530: 20 20 20 20 20 69 66 20 62 43 6f 6d 6d 61 3a 0a       if bComma:.
1540: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1550: 73 4a 53 4f 4e 20 2b 3d 20 22 2c 5c 6e 22 0a 20  sJSON += ",\n". 
1560: 20 20 20 20 20 20 20 20 20 20 20 73 4a 53 4f 4e             sJSON
1570: 20 2b 3d 20 73 54 65 78 74 0a 20 20 20 20 20 20   += sText.      
1580: 20 20 20 20 20 20 62 43 6f 6d 6d 61 20 3d 20 54        bComma = T
1590: 72 75 65 0a 20 20 20 20 73 4a 53 4f 4e 20 2b 3d  rue.    sJSON +=
15a0: 20 22 5c 6e 5d 7d 5c 6e 22 0a 20 20 20 20 72 65   "\n]}\n".    re
15b0: 74 75 72 6e 20 73 4a 53 4f 4e 0a 0a 40 61 70 70  turn sJSON..@app
15c0: 2e 72 6f 75 74 65 28 22 2f 73 65 74 5f 6f 70 74  .route("/set_opt
15d0: 69 6f 6e 73 2f 66 72 22 2c 20 6d 65 74 68 6f 64  ions/fr", method
15e0: 3d 22 50 4f 53 54 22 29 0a 64 65 66 20 73 65 74  ="POST").def set
15f0: 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20  Options ():.    
1600: 22 73 65 74 20 67 72 61 6d 6d 61 72 20 6f 70 74  "set grammar opt
1610: 69 6f 6e 73 20 66 6f 72 20 63 75 72 72 65 6e 74  ions for current
1620: 20 75 73 65 72 22 0a 20 20 20 20 69 66 20 72 65   user".    if re
1630: 71 75 65 73 74 2e 66 6f 72 6d 73 2e 6f 70 74 69  quest.forms.opti
1640: 6f 6e 73 3a 0a 20 20 20 20 20 20 20 20 73 55 73  ons:.        sUs
1650: 65 72 49 64 20 3d 20 72 65 71 75 65 73 74 2e 63  erId = request.c
1660: 6f 6f 6b 69 65 73 2e 75 73 65 72 5f 69 64 20 20  ookies.user_id  
1670: 69 66 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69  if request.cooki
1680: 65 73 2e 75 73 65 72 5f 69 64 20 20 65 6c 73 65  es.user_id  else
1690: 20 6e 65 78 74 28 75 73 65 72 47 65 6e 65 72 61   next(userGenera
16a0: 74 6f 72 29 0a 20 20 20 20 20 20 20 20 64 4f 70  tor).        dOp
16b0: 74 69 6f 6e 73 20 3d 20 64 55 73 65 72 5b 73 55  tions = dUser[sU
16c0: 73 65 72 49 64 5d 5b 22 67 63 5f 6f 70 74 69 6f  serId]["gc_optio
16d0: 6e 73 22 5d 20 20 69 66 20 73 55 73 65 72 49 64  ns"]  if sUserId
16e0: 20 69 6e 20 64 55 73 65 72 20 20 65 6c 73 65 20   in dUser  else 
16f0: 64 69 63 74 28 64 47 43 4f 70 74 69 6f 6e 73 29  dict(dGCOptions)
1700: 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20 20  .        try:.  
1710: 20 20 20 20 20 20 20 20 20 20 64 4f 70 74 69 6f            dOptio
1720: 6e 73 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e 6c  ns.update(json.l
1730: 6f 61 64 73 28 72 65 71 75 65 73 74 2e 66 6f 72  oads(request.for
1740: 6d 73 2e 6f 70 74 69 6f 6e 73 29 29 0a 20 20 20  ms.options)).   
1750: 20 20 20 20 20 20 20 20 20 64 55 73 65 72 5b 73           dUser[s
1760: 55 73 65 72 49 64 5d 20 3d 20 7b 20 22 74 69 6d  UserId] = { "tim
1770: 65 22 3a 20 69 6e 74 28 74 69 6d 65 2e 74 69 6d  e": int(time.tim
1780: 65 28 29 29 2c 20 22 67 63 5f 6f 70 74 69 6f 6e  e()), "gc_option
1790: 73 22 3a 20 64 4f 70 74 69 6f 6e 73 20 7d 0a 20  s": dOptions }. 
17a0: 20 20 20 20 20 20 20 20 20 20 20 72 65 73 70 6f             respo
17b0: 6e 73 65 2e 73 65 74 5f 63 6f 6f 6b 69 65 28 22  nse.set_cookie("
17c0: 75 73 65 72 5f 69 64 22 2c 20 73 55 73 65 72 49  user_id", sUserI
17d0: 64 2c 20 70 61 74 68 3d 22 2f 22 2c 20 6d 61 78  d, path="/", max
17e0: 5f 61 67 65 3d 38 36 34 30 30 29 20 23 20 32 34  _age=86400) # 24
17f0: 68 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65  h.            re
1800: 74 75 72 6e 20 6a 73 6f 6e 2e 64 75 6d 70 73 28  turn json.dumps(
1810: 64 55 73 65 72 5b 73 55 73 65 72 49 64 5d 5b 22  dUser[sUserId]["
1820: 67 63 5f 6f 70 74 69 6f 6e 73 22 5d 29 0a 20 20  gc_options"]).  
1830: 20 20 20 20 20 20 65 78 63 65 70 74 20 28 4b 65        except (Ke
1840: 79 45 72 72 6f 72 2c 20 6a 73 6f 6e 2e 4a 53 4f  yError, json.JSO
1850: 4e 44 65 63 6f 64 65 45 72 72 6f 72 29 3a 0a 20  NDecodeError):. 
1860: 20 20 20 20 20 20 20 20 20 20 20 74 72 61 63 65             trace
1870: 62 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29  back.print_exc()
1880: 0a 20 20 20 20 20 20 20 20 20 20 20 20 72 65 74  .            ret
1890: 75 72 6e 20 27 7b 22 65 72 72 6f 72 22 3a 20 22  urn '{"error": "
18a0: 6f 70 74 69 6f 6e 73 20 6e 6f 74 20 72 65 67 69  options not regi
18b0: 73 74 65 72 65 64 22 7d 27 0a 20 20 20 20 72 65  stered"}'.    re
18c0: 74 75 72 6e 20 27 7b 22 65 72 72 6f 72 22 3a 20  turn '{"error": 
18d0: 22 6e 6f 20 6f 70 74 69 6f 6e 73 20 72 65 63 65  "no options rece
18e0: 69 76 65 64 22 7d 27 0a 0a 40 61 70 70 2e 72 6f  ived"}'..@app.ro
18f0: 75 74 65 28 22 2f 72 65 73 65 74 5f 6f 70 74 69  ute("/reset_opti
1900: 6f 6e 73 2f 66 72 22 2c 20 6d 65 74 68 6f 64 3d  ons/fr", method=
1910: 22 50 4f 53 54 22 29 0a 64 65 66 20 72 65 73 65  "POST").def rese
1920: 74 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20  tOptions ():.   
1930: 20 22 64 65 66 61 75 6c 74 20 67 72 61 6d 6d 61   "default gramma
1940: 72 20 6f 70 74 69 6f 6e 73 22 0a 20 20 20 20 69  r options".    i
1950: 66 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69 65  f request.cookie
1960: 73 2e 75 73 65 72 5f 69 64 20 61 6e 64 20 72 65  s.user_id and re
1970: 71 75 65 73 74 2e 63 6f 6f 6b 69 65 73 2e 75 73  quest.cookies.us
1980: 65 72 5f 69 64 20 69 6e 20 64 55 73 65 72 3a 0a  er_id in dUser:.
1990: 20 20 20 20 20 20 20 20 64 65 6c 20 64 55 73 65          del dUse
19a0: 72 5b 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69 65  r[request.cookie
19b0: 73 2e 75 73 65 72 5f 69 64 5d 0a 20 20 20 20 72  s.user_id].    r
19c0: 65 74 75 72 6e 20 22 64 6f 6e 65 22 0a 0a 40 61  eturn "done"..@a
19d0: 70 70 2e 72 6f 75 74 65 28 22 2f 66 6f 72 6d 61  pp.route("/forma
19e0: 74 5f 74 65 78 74 2f 66 72 22 2c 20 6d 65 74 68  t_text/fr", meth
19f0: 6f 64 3d 22 50 4f 53 54 22 29 0a 64 65 66 20 66  od="POST").def f
1a00: 6f 72 6d 61 74 54 65 78 74 20 28 29 3a 0a 20 20  ormatText ():.  
1a10: 20 20 22 61 70 70 6c 79 20 74 68 65 20 74 65 78    "apply the tex
1a20: 74 20 66 6f 72 6d 61 74 74 65 72 20 61 6e 64 20  t formatter and 
1a30: 72 65 74 75 72 6e 73 20 74 65 78 74 22 0a 20 20  returns text".  
1a40: 20 20 72 65 74 75 72 6e 20 6f 54 65 78 74 46 6f    return oTextFo
1a50: 72 6d 61 74 74 65 72 2e 66 6f 72 6d 61 74 54 65  rmatter.formatTe
1a60: 78 74 28 72 65 71 75 65 73 74 2e 66 6f 72 6d 73  xt(request.forms
1a70: 2e 74 65 78 74 29 0a 0a 23 40 61 70 70 2e 72 6f  .text)..#@app.ro
1a80: 75 74 65 28 27 2f 73 74 61 74 69 63 2f 3c 66 69  ute('/static/<fi
1a90: 6c 65 70 61 74 68 3a 70 61 74 68 3e 27 29 0a 23  lepath:path>').#
1aa0: 64 65 66 20 73 65 72 76 65 72 5f 73 74 61 74 69  def server_stati
1ab0: 63 20 28 66 69 6c 65 70 61 74 68 29 3a 0a 23 20  c (filepath):.# 
1ac0: 20 20 20 72 65 74 75 72 6e 20 73 74 61 74 69 63     return static
1ad0: 5f 66 69 6c 65 28 66 69 6c 65 70 61 74 68 2c 20  _file(filepath, 
1ae0: 72 6f 6f 74 3d 27 2e 2f 76 69 65 77 73 2f 73 74  root='./views/st
1af0: 61 74 69 63 27 29 0a 0a 0a 64 65 66 20 70 75 72  atic')...def pur
1b00: 67 65 55 73 65 72 73 20 28 29 3a 0a 20 20 20 20  geUsers ():.    
1b10: 22 64 65 6c 65 74 65 20 75 73 65 72 20 6f 70 74  "delete user opt
1b20: 69 6f 6e 73 20 6f 6c 64 65 72 20 74 68 61 6e 20  ions older than 
1b30: 6e 20 68 6f 75 72 73 22 0a 20 20 20 20 74 72 79  n hours".    try
1b40: 3a 0a 20 20 20 20 20 20 20 20 6e 4e 6f 77 4d 69  :.        nNowMi
1b50: 6e 75 73 4e 48 6f 75 72 73 20 3d 20 69 6e 74 28  nusNHours = int(
1b60: 74 69 6d 65 2e 74 69 6d 65 28 29 29 20 2d 20 28  time.time()) - (
1b70: 69 6e 74 28 72 65 71 75 65 73 74 2e 66 6f 72 6d  int(request.form
1b80: 73 2e 68 6f 75 72 73 29 20 2a 20 36 30 20 2a 20  s.hours) * 60 * 
1b90: 36 30 29 0a 20 20 20 20 20 20 20 20 66 6f 72 20  60).        for 
1ba0: 6e 55 73 65 72 49 64 2c 20 64 56 61 6c 75 65 20  nUserId, dValue 
1bb0: 69 6e 20 64 55 73 65 72 2e 69 74 65 6d 73 28 29  in dUser.items()
1bc0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66  :.            if
1bd0: 20 64 56 61 6c 75 65 5b 22 74 69 6d 65 22 5d 20   dValue["time"] 
1be0: 3c 20 6e 4e 6f 77 4d 69 6e 75 73 4e 48 6f 75 72  < nNowMinusNHour
1bf0: 73 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  s:.             
1c00: 20 20 20 64 65 6c 20 64 55 73 65 72 5b 6e 55 73     del dUser[nUs
1c10: 65 72 49 64 5d 0a 20 20 20 20 20 20 20 20 72 65  erId].        re
1c20: 74 75 72 6e 20 54 72 75 65 0a 20 20 20 20 65 78  turn True.    ex
1c30: 63 65 70 74 20 4b 65 79 45 72 72 6f 72 3a 0a 20  cept KeyError:. 
1c40: 20 20 20 20 20 20 20 74 72 61 63 65 62 61 63 6b         traceback
1c50: 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a 20 20 20  .print_exc().   
1c60: 20 20 20 20 20 72 65 74 75 72 6e 20 46 61 6c 73       return Fals
1c70: 65 0a 0a 0a 23 20 45 52 52 4f 52 0a 40 61 70 70  e...# ERROR.@app
1c80: 2e 65 72 72 6f 72 28 34 30 34 29 0a 64 65 66 20  .error(404).def 
1c90: 65 72 72 6f 72 34 30 34 20 28 65 72 72 6f 72 29  error404 (error)
1ca0: 3a 0a 20 20 20 20 22 34 30 34 20 65 72 72 6f 72  :.    "404 error
1cb0: 20 70 61 67 65 22 0a 20 20 20 20 72 65 74 75 72   page".    retur
1cc0: 6e 20 27 45 72 72 6f 72 20 34 30 34 2e 3c 62 72  n 'Error 404.<br
1cd0: 2f 3e 27 20 2b 20 73 74 72 28 65 72 72 6f 72 29  />' + str(error)
1ce0: 0a 0a 0a 23 20 69 6e 69 74 69 61 6c 69 73 61 74  ...# initialisat
1cf0: 69 6f 6e 0a 6f 47 72 61 6d 6d 61 72 43 68 65 63  ion.oGrammarChec
1d00: 6b 65 72 20 3d 20 67 72 61 6d 6d 61 6c 65 63 74  ker = grammalect
1d10: 65 2e 47 72 61 6d 6d 61 72 43 68 65 63 6b 65 72  e.GrammarChecker
1d20: 28 22 66 72 22 2c 20 22 53 65 72 76 65 72 22 29  ("fr", "Server")
1d30: 0a 6f 53 70 65 6c 6c 43 68 65 63 6b 65 72 20 3d  .oSpellChecker =
1d40: 20 6f 47 72 61 6d 6d 61 72 43 68 65 63 6b 65 72   oGrammarChecker
1d50: 2e 67 65 74 53 70 65 6c 6c 43 68 65 63 6b 65 72  .getSpellChecker
1d60: 28 29 0a 6f 4c 65 78 69 63 6f 67 72 61 70 68 65  ().oLexicographe
1d70: 72 20 3d 20 6f 47 72 61 6d 6d 61 72 43 68 65 63  r = oGrammarChec
1d80: 6b 65 72 2e 67 65 74 4c 65 78 69 63 6f 67 72 61  ker.getLexicogra
1d90: 70 68 65 72 28 29 0a 6f 54 65 78 74 46 6f 72 6d  pher().oTextForm
1da0: 61 74 74 65 72 20 3d 20 6f 47 72 61 6d 6d 61 72  atter = oGrammar
1db0: 43 68 65 63 6b 65 72 2e 67 65 74 54 65 78 74 46  Checker.getTextF
1dc0: 6f 72 6d 61 74 74 65 72 28 29 0a 67 63 65 20 3d  ormatter().gce =
1dd0: 20 6f 47 72 61 6d 6d 61 72 43 68 65 63 6b 65 72   oGrammarChecker
1de0: 2e 67 65 74 47 43 45 6e 67 69 6e 65 28 29 0a 0a  .getGCEngine()..
1df0: 64 47 43 4f 70 74 69 6f 6e 73 20 3d 20 67 63 65  dGCOptions = gce
1e00: 2e 67 65 74 4f 70 74 69 6f 6e 73 28 29 0a 64 55  .getOptions().dU
1e10: 73 65 72 20 3d 20 7b 7d 0a 75 73 65 72 47 65 6e  ser = {}.userGen
1e20: 65 72 61 74 6f 72 20 3d 20 67 65 6e 55 73 65 72  erator = genUser
1e30: 49 64 28 29 0a 0a 0a 64 65 66 20 6d 61 69 6e 20  Id()...def main 
1e40: 28 73 48 6f 73 74 3d 22 6c 6f 63 61 6c 68 6f 73  (sHost="localhos
1e50: 74 22 2c 20 6e 50 6f 72 74 3d 38 30 38 30 2c 20  t", nPort=8080, 
1e60: 64 4f 70 74 69 6f 6e 73 3d 4e 6f 6e 65 2c 20 62  dOptions=None, b
1e70: 54 65 73 74 50 61 67 65 3d 46 61 6c 73 65 29 3a  TestPage=False):
1e80: 0a 20 20 20 20 22 73 74 61 72 74 20 73 65 72 76  .    "start serv
1e90: 65 72 22 0a 20 20 20 20 67 6c 6f 62 61 6c 20 64  er".    global d
1ea0: 47 43 4f 70 74 69 6f 6e 73 0a 20 20 20 20 67 6c  GCOptions.    gl
1eb0: 6f 62 61 6c 20 54 45 53 54 50 41 47 45 0a 20 20  obal TESTPAGE.  
1ec0: 20 20 67 6c 6f 62 61 6c 20 48 4f 4d 45 50 41 47    global HOMEPAG
1ed0: 45 0a 0a 20 20 20 20 69 66 20 62 54 65 73 74 50  E..    if bTestP
1ee0: 61 67 65 3a 0a 20 20 20 20 20 20 20 20 54 45 53  age:.        TES
1ef0: 54 50 41 47 45 20 3d 20 54 72 75 65 0a 20 20 20  TPAGE = True.   
1f00: 20 20 20 20 20 48 4f 4d 45 50 41 47 45 20 3d 20       HOMEPAGE = 
1f10: 48 4f 4d 45 50 41 47 45 2e 72 65 70 6c 61 63 65  HOMEPAGE.replace
1f20: 28 22 7b 53 45 52 56 45 52 5f 50 4f 52 54 7d 22  ("{SERVER_PORT}"
1f30: 2c 20 73 74 72 28 6e 50 6f 72 74 29 29 0a 20 20  , str(nPort)).  
1f40: 20 20 69 66 20 64 4f 70 74 69 6f 6e 73 3a 0a 20    if dOptions:. 
1f50: 20 20 20 20 20 20 20 6f 47 72 61 6d 6d 61 72 43         oGrammarC
1f60: 68 65 63 6b 65 72 2e 67 63 65 2e 73 65 74 4f 70  hecker.gce.setOp
1f70: 74 69 6f 6e 73 28 64 4f 70 74 69 6f 6e 73 29 0a  tions(dOptions).
1f80: 20 20 20 20 20 20 20 20 64 47 43 4f 70 74 69 6f          dGCOptio
1f90: 6e 73 20 3d 20 67 63 65 2e 67 65 74 4f 70 74 69  ns = gce.getOpti
1fa0: 6f 6e 73 28 29 0a 0a 20 20 20 20 70 72 69 6e 74  ons()..    print
1fb0: 28 22 50 79 74 68 6f 6e 3a 20 22 20 2b 20 73 79  ("Python: " + sy
1fc0: 73 2e 76 65 72 73 69 6f 6e 29 0a 20 20 20 20 65  s.version).    e
1fd0: 63 68 6f 28 22 47 72 61 6d 6d 61 6c 65 63 74 65  cho("Grammalecte
1fe0: 20 76 7b 7d 22 2e 66 6f 72 6d 61 74 28 67 63 65   v{}".format(gce
1ff0: 2e 76 65 72 73 69 6f 6e 29 29 0a 20 20 20 20 65  .version)).    e
2000: 63 68 6f 28 22 47 72 61 6d 6d 61 72 20 6f 70 74  cho("Grammar opt
2010: 69 6f 6e 73 3a 5c 6e 22 20 2b 20 22 20 7c 20 22  ions:\n" + " | "
2020: 2e 6a 6f 69 6e 28 5b 20 6b 20 2b 20 22 3a 20 22  .join([ k + ": "
2030: 20 2b 20 73 74 72 28 76 29 20 20 66 6f 72 20 6b   + str(v)  for k
2040: 2c 20 76 20 69 6e 20 73 6f 72 74 65 64 28 64 47  , v in sorted(dG
2050: 43 4f 70 74 69 6f 6e 73 2e 69 74 65 6d 73 28 29  COptions.items()
2060: 29 20 5d 29 29 0a 20 20 20 20 72 75 6e 28 61 70  ) ])).    run(ap
2070: 70 2c 20 68 6f 73 74 3d 73 48 6f 73 74 2c 20 70  p, host=sHost, p
2080: 6f 72 74 3d 6e 50 6f 72 74 29 0a 0a 0a 69 66 20  ort=nPort)...if 
2090: 5f 5f 6e 61 6d 65 5f 5f 20 3d 3d 20 27 5f 5f 6d  __name__ == '__m
20a0: 61 69 6e 5f 5f 27 3a 0a 20 20 20 20 78 50 61 72  ain__':.    xPar
20b0: 73 65 72 20 3d 20 61 72 67 70 61 72 73 65 2e 41  ser = argparse.A
20c0: 72 67 75 6d 65 6e 74 50 61 72 73 65 72 28 29 0a  rgumentParser().
20d0: 20 20 20 20 23 78 50 61 72 73 65 72 2e 61 64 64      #xParser.add
20e0: 5f 61 72 67 75 6d 65 6e 74 28 22 6c 61 6e 67 22  _argument("lang"
20f0: 2c 20 74 79 70 65 3d 73 74 72 2c 20 6e 61 72 67  , type=str, narg
2100: 73 3d 27 2b 27 2c 20 68 65 6c 70 3d 22 6c 61 6e  s='+', help="lan
2110: 67 20 70 72 6f 6a 65 63 74 20 74 6f 20 67 65 6e  g project to gen
2120: 65 72 61 74 65 20 28 6e 61 6d 65 20 6f 66 20 66  erate (name of f
2130: 6f 6c 64 65 72 20 69 6e 20 2f 6c 61 6e 67 29 22  older in /lang)"
2140: 29 0a 20 20 20 20 78 50 61 72 73 65 72 2e 61 64  ).    xParser.ad
2150: 64 5f 61 72 67 75 6d 65 6e 74 28 22 2d 68 74 22  d_argument("-ht"
2160: 2c 20 22 2d 2d 68 6f 73 74 22 2c 20 68 65 6c 70  , "--host", help
2170: 3d 22 68 6f 73 74 20 28 64 65 66 61 75 6c 74 3a  ="host (default:
2180: 20 6c 6f 63 61 6c 68 6f 73 74 29 22 2c 20 74 79   localhost)", ty
2190: 70 65 3d 73 74 72 29 0a 20 20 20 20 78 50 61 72  pe=str).    xPar
21a0: 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74  ser.add_argument
21b0: 28 22 2d 70 22 2c 20 22 2d 2d 70 6f 72 74 22 2c  ("-p", "--port",
21c0: 20 68 65 6c 70 3d 22 70 6f 72 74 20 28 64 65 66   help="port (def
21d0: 61 75 6c 74 3a 20 38 30 38 30 29 22 2c 20 74 79  ault: 8080)", ty
21e0: 70 65 3d 69 6e 74 29 0a 20 20 20 20 78 50 61 72  pe=int).    xPar
21f0: 73 65 72 2e 61 64 64 5f 61 72 67 75 6d 65 6e 74  ser.add_argument
2200: 28 22 2d 74 22 2c 20 22 2d 2d 74 65 73 74 5f 70  ("-t", "--test_p
2210: 61 67 65 22 2c 20 68 65 6c 70 3d 22 70 61 67 65  age", help="page
2220: 20 74 6f 20 74 65 73 74 20 74 68 65 20 73 65 72   to test the ser
2230: 76 65 72 20 6f 6e 20 2f 22 2c 20 61 63 74 69 6f  ver on /", actio
2240: 6e 3d 22 73 74 6f 72 65 5f 74 72 75 65 22 29 0a  n="store_true").
2250: 20 20 20 20 78 50 61 72 73 65 72 2e 61 64 64 5f      xParser.add_
2260: 61 72 67 75 6d 65 6e 74 28 22 2d 6f 6e 22 2c 20  argument("-on", 
2270: 22 2d 2d 6f 70 74 5f 6f 6e 22 2c 20 6e 61 72 67  "--opt_on", narg
2280: 73 3d 22 2b 22 2c 20 68 65 6c 70 3d 22 61 63 74  s="+", help="act
2290: 69 76 61 74 65 20 6f 70 74 69 6f 6e 73 22 29 0a  ivate options").
22a0: 20 20 20 20 78 50 61 72 73 65 72 2e 61 64 64 5f      xParser.add_
22b0: 61 72 67 75 6d 65 6e 74 28 22 2d 6f 66 66 22 2c  argument("-off",
22c0: 20 22 2d 2d 6f 70 74 5f 6f 66 66 22 2c 20 6e 61   "--opt_off", na
22d0: 72 67 73 3d 22 2b 22 2c 20 68 65 6c 70 3d 22 64  rgs="+", help="d
22e0: 65 61 63 74 69 76 61 74 65 20 6f 70 74 69 6f 6e  eactivate option
22f0: 73 22 29 0a 20 20 20 20 78 41 72 67 73 20 3d 20  s").    xArgs = 
2300: 78 50 61 72 73 65 72 2e 70 61 72 73 65 5f 61 72  xParser.parse_ar
2310: 67 73 28 29 0a 0a 20 20 20 20 64 4f 70 74 20 3d  gs()..    dOpt =
2320: 20 4e 6f 6e 65 0a 20 20 20 20 69 66 20 78 41 72   None.    if xAr
2330: 67 73 2e 6f 70 74 5f 6f 6e 20 20 6f 72 20 20 78  gs.opt_on  or  x
2340: 41 72 67 73 2e 6f 70 74 5f 6f 66 66 3a 0a 20 20  Args.opt_off:.  
2350: 20 20 20 20 20 20 64 4f 70 74 20 3d 20 7b 7d 0a        dOpt = {}.
2360: 20 20 20 20 20 20 20 20 69 66 20 78 41 72 67 73          if xArgs
2370: 2e 6f 70 74 5f 6f 6e 3a 0a 20 20 20 20 20 20 20  .opt_on:.       
2380: 20 20 20 20 20 64 4f 70 74 20 3d 20 7b 20 6f 70       dOpt = { op
2390: 74 3a 54 72 75 65 20 20 66 6f 72 20 6f 70 74 20  t:True  for opt 
23a0: 69 6e 20 78 41 72 67 73 2e 6f 70 74 5f 6f 6e 20  in xArgs.opt_on 
23b0: 7d 0a 20 20 20 20 20 20 20 20 69 66 20 78 41 72  }.        if xAr
23c0: 67 73 2e 6f 70 74 5f 6f 66 66 3a 0a 20 20 20 20  gs.opt_off:.    
23d0: 20 20 20 20 20 20 20 20 64 4f 70 74 2e 75 70 64          dOpt.upd
23e0: 61 74 65 28 7b 20 6f 70 74 3a 46 61 6c 73 65 20  ate({ opt:False 
23f0: 20 66 6f 72 20 6f 70 74 20 69 6e 20 78 41 72 67   for opt in xArg
2400: 73 2e 6f 70 74 5f 6f 66 66 20 7d 29 0a 0a 20 20  s.opt_off })..  
2410: 20 20 6d 61 69 6e 28 78 41 72 67 73 2e 68 6f 73    main(xArgs.hos
2420: 74 20 6f 72 20 22 6c 6f 63 61 6c 68 6f 73 74 22  t or "localhost"
2430: 2c 20 5c 0a 20 20 20 20 20 20 20 20 20 78 41 72  , \.         xAr
2440: 67 73 2e 70 6f 72 74 20 6f 72 20 38 30 38 30 2c  gs.port or 8080,
2450: 20 5c 0a 20 20 20 20 20 20 20 20 20 64 4f 70 74   \.         dOpt
2460: 2c 0a 20 20 20 20 20 20 20 20 20 78 41 72 67 73  ,.         xArgs
2470: 2e 74 65 73 74 5f 70 61 67 65 29 0a              .test_page).