/ webapp.py
webapp.py
1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 # 4 # Copyright © 2013 Jeff Epler <jepler@unpythonic.net> 5 # 6 # This program is free software; you can redistribute it and/or modify 7 # it under the terms of the GNU General Public License as published by 8 # the Free Software Foundation; either version 2 of the License, or 9 # (at your option) any later version. 10 # 11 # This program is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 # GNU General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 # 20 import subprocess 21 import threading 22 import sys 23 import os 24 import cgi 25 import traceback 26 import errno 27 import ana 28 29 d = ana.from_binary('dict.bin') 30 31 def query(pi): 32 return d.run(pi) 33 34 35 # Every WSGI application must have an application object - a callable 36 # object that accepts two arguments. For that purpose, we're going to 37 # use a function (note that you're not limited to a function, you can 38 # use a class for example). The first argument passed to the function 39 # is a dictionary containing CGI-style envrironment variables and the 40 # second variable is the callable object (see PEP 333). 41 def anagram_app(environ, start_response): 42 status = '200 OK' # HTTP Status 43 44 pi = environ['QUERY_STRING'] 45 pi = cgi.parse_qs(pi) 46 plain = pi.get('p', False) 47 if pi: 48 pi = pi.get('q', [''])[-1] 49 else: 50 pi = '' 51 52 if plain: 53 headers = [('Content-type', 'application/octet-stream')] # HTTP Headers 54 else: 55 headers = [('Content-type', 'text/html')] # HTTP Headers 56 start_response(status, headers) 57 58 if not plain: 59 yield '''<!DOCTYPE html> 60 <html> 61 <meta charset="UTF-8"> 62 <meta name="viewport" content="width=device-width"> 63 <head> 64 <title>Surly Anagram Server</title> 65 <style> 66 @media screen and (min-width: 680px) { #cheatsheet { float: right; } } 67 #cheatsheet { font-size: 71%%; cursor: pointer; } 68 #cheatsheet table, #cheatsheet caption { background: #d9d9d9; color: #000; } 69 #cheatsheet.hidden { cursor: zoom-in; } 70 #cheatsheet caption:after { content: "\\a0«" } 71 #cheatsheet.hidden caption:after { content: "\\a0»" } 72 #cheatsheet.hidden tbody { display: none; } 73 //#cheatsheet { float: right; } 74 #cheatsheet th { text-align: left } 75 #cheatsheet caption { font-weight: bold; } 76 </style> 77 </head> 78 <body> 79 <div id="cheatsheet"> 80 <table> 81 <caption>Cheatsheet</caption> 82 <tr><th>letters... <td> Letters available to anagram 83 <tr><th>=word <td> word must be in result 84 <tr><th>>n <td> words must contain at least n letters 85 <tr><th><n <td> words must contain at most n letters 86 <tr><th>' <td> words with apostrophes are considered 87 <tr><th>n <td> choose a word with exactly n letters 88 <tr><th>-n <td> display at most n results (limit 1000) 89 <tr><th>? <td> display candidate words, not whole phrases 90 <tr><td colspan=2>In ajax mode, hit enter or click "anagram" to do get full results 91 <tr><td colspan=2>Source (web app and unix commandline program) on 92 <a href="https://github.com/jepler/anagram">github</a> 93 </table> 94 </div> 95 96 <form id="f"><input type="text" id="query" name="q" value="%s"> 97 <input type="submit" value="anagram"> 98 <script>document.getElementById("query").focus()</script> 99 </form> 100 <pre id="results">''' % cgi.escape(pi, True) 101 102 if pi: 103 if plain: e = lambda x: x 104 else: e = cgi.escape 105 yield '# Query: ' + e(repr(pi)) + '\n' 106 107 for row in query(pi): 108 yield e(row) + '\n' 109 110 if not plain: 111 yield ''' 112 </pre> 113 <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 114 <script src="anagram.js"></script> 115 <script> 116 $("#cheatsheet").click(function() { $(this).toggleClass("hidden"); }) 117 </script> 118 </body></html>''' 119 120 from flup.server.fcgi import WSGIServer 121 WSGIServer(anagram_app).run()