forked from UO-CIS-322/proj3-anagrams
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flask_vocab.py
182 lines (148 loc) · 4.92 KB
/
flask_vocab.py
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
180
181
"""
Simple Flask web site
"""
import flask
# from flask import render_template
from flask import request # Data from a submitted form
from flask import url_for
from flask import jsonify # For AJAX transactions
import json
import logging
import argparse # For the vocabulary list
import sys
# Our own modules
from letterbag import LetterBag
from vocab import Vocab
from jumble import jumbled
###
# Globals
###
app = flask.Flask(__name__)
import CONFIG
app.secret_key = CONFIG.COOKIE_KEY # Should allow using session variables
#
# One shared 'Vocab' object, read-only after initialization,
# shared by all threads and instances. Otherwise we would have to
# store it in the browser and transmit it on each request/response cycle,
# or else read it from the file on each request/responce cycle,
# neither of which would be suitable for responding keystroke by keystroke.
#
def get_command_line():
"""
Returns a namespace of command-line argument values
"""
parser = argparse.ArgumentParser(
description="Vocabulary anagram through a web server")
parser.add_argument("vocab", type=argparse.FileType('r'),
default="data/vocab.txt",
help="A file containing vocabulary words, one per line")
args = parser.parse_args()
return args
CMDLN = get_command_line()
WORDS = Vocab( CMDLN.vocab )
###
# Pages
###
@app.route("/")
@app.route("/index")
def index():
flask.g.vocab = WORDS.as_list();
flask.session["target_count"] = min( len(flask.g.vocab), CONFIG.SUCCESS_COUNT )
flask.session["jumble"] = jumbled(flask.g.vocab, flask.session["target_count"])
flask.session["matches"] = [ ]
app.logger.debug("Session variables have been set")
assert flask.session["matches"] == [ ]
assert flask.session["target_count"] > 0
app.logger.debug("At least one seems to be set correctly")
return flask.render_template('vocab.html')
@app.route("/keep_going")
def keep_going():
"""
After initial use of index, we keep the same scrambled
word and try to get more matches
"""
flask.g.vocab = WORDS.as_list();
return flask.render_template('vocab.html')
@app.route("/success")
def success():
return flask.render_template('success.html')
#######################
# JSON request handler
#######################
@app.route("/_check")
def check():
"""
The user has pressed a key. We respond by sending back 2
booleans and 1 list. The first boolean we send back is whether
all the characters in the text that the user has typed in so far
are in the jumble/anagram word. The second boolean we send back
is whether the text the user has typed in so far is a word that is
in the list of vocabulary words. Lastly, we send back a list of all
the words in the vocabulary list that contain all the letters that
have been typed so far by the user.
"""
app.logger.debug("Entering check")
text = request.args.get("text", type=str)
jumble = request.args.get("jumble", type=str)
## Is it good?
in_jumble = LetterBag(jumble).contains(text) #all letters are in the jumble/anagram word
matched = WORDS.has(text) #the text is a word that is in the list of vocab words
highlight_list = []
for word in WORDS.as_list():
if (LetterBag(word).contains(text)):
highlight_list.append(word)
rslt = { "in_jumble": in_jumble, "matched": matched, "highlight_list": highlight_list }
return jsonify(result=rslt)
###############
# AJAX request handlers
# These return JSON, rather than rendering pages.
###############
@app.route("/_example")
def example():
"""
Example ajax request handler
"""
app.logger.debug("Got a JSON request");
rslt = { "key": "value" }
return jsonify(result=rslt)
#################
# Functions used within the templates
#################
@app.template_filter( 'filt' )
def format_filt( something ):
"""
Example of a filter that can be used within
the Jinja2 code
"""
return "Not what you asked for"
###################
# Error handlers
###################
@app.errorhandler(404)
def error_404(e):
app.logger.warning("++ 404 error: {}".format(e))
return flask.render_template('404.html'), 404
@app.errorhandler(500)
def error_500(e):
app.logger.warning("++ 500 error: {}".format(e))
assert app.debug == False # I want to invoke the debugger
return flask.render_template('500.html'), 500
@app.errorhandler(403)
def error_403(e):
app.logger.warning("++ 403 error: {}".format(e))
return flask.render_template('403.html'), 403
#############
# Set up to run from cgi-bin script, from
# gunicorn, or stand-alone.
#
if __name__ == "__main__":
# Standalone.
app.debug = True
app.logger.setLevel(logging.DEBUG)
print("Opening for global access on port {}".format(CONFIG.PORT))
app.run(port=CONFIG.PORT, host="0.0.0.0")
else:
# Running from cgi-bin or from gunicorn WSGI server,
# which makes the call to app.run. Gunicorn may invoke more than
# one instance for concurrent service.
app.debug=False