Files
exercises-in-programming-style/15-restful/tf-15.py
Bruce Adams 5749c2c50f Enhance testing: run all executables
Add a #! line at the beginning of each of the existing Python programs
and change these files to be executable. This sets the stage for having
the test script blindly run anything that is executable, adding support
for testing many programming languages.
2013-09-24 22:09:30 -04:00

111 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python
import re, string, sys
with open("../stop_words.txt") as f:
stops = set(f.read().split(",") + list(string.ascii_lowercase))
# The "database"
data = {}
# Internal functions of the "server"-side application
def error_state():
return "Something wrong", ["get", "default", None]
# The "server"-side application handlers
def quit_handler(args):
sys.exit("Goodbye cruel world...")
def default_get_handler(args):
rep = "What would you like to do?"
rep += "\n1 - Quit" + "\n2 - Upload file"
links = {"1" : ["post", "execution", None], "2" : ["get", "file_form", None]}
return rep, links
def upload_get_handler(args):
return "Name of file to upload?", ["post", "file"]
def upload_post_handler(args):
def create_data(filename):
if filename in data:
return
word_freqs = {}
print "Trying to open " + filename
with open(filename) as f:
for w in [x.lower() for x in re.split("[^a-zA-Z]+", f.read()) if len(x) > 0 and x.lower() not in stops]:
word_freqs[w] = word_freqs.get(w, 0) + 1
word_freqsl = word_freqs.items()
word_freqsl.sort(lambda x, y: cmp(y[1], x[1]))
data[filename] = word_freqsl
if args == None:
return error_state()
filename = args[0]
try:
create_data(filename)
except:
return error_state()
return word_get_handler([filename, 0])
def word_get_handler(args):
def get_word(filename, word_index):
if word_index < len(data[filename]):
return data[filename][word_index]
else:
return ("no more words", 0)
filename = args[0]; word_index = args[1]
word_info = get_word(filename, word_index)
rep = '\n#{0}: {1} - {2}'.format(word_index+1, word_info[0], word_info[1])
rep += "\n\nWhat would you like to do next?"
rep += "\n1 - Quit" + "\n2 - Upload file"
rep += "\n3 - See next most-frequently occurring word"
links = {"1" : ["post", "execution", None],
"2" : ["get", "file_form", None],
"3" : ["get", "word", [filename, word_index+1]]}
return rep, links
# Handler registration
handlers = {"post_execution" : quit_handler,
"get_default" : default_get_handler,
"get_file_form" : upload_get_handler,
"post_file" : upload_post_handler,
"get_word" : word_get_handler }
# The "server" core
def handle_request(verb, uri, args):
def handler_key(verb, uri):
return verb + "_" + uri
if handler_key(verb, uri) in handlers:
return handlers[handler_key(verb, uri)](args)
else:
return handlers[handler_key("get", "default")](args)
# A very simple client "browser"
def render_and_get_input(state_representation, links):
print state_representation
if type(links) is dict: # many possible next states
input = sys.stdin.readline().strip()
if input in links:
return links[input]
else:
return ["get", "default", None]
elif type(links) is list: # only one possible next state
if links[0] == "post": # get "form" data
input = sys.stdin.readline().strip()
links.append([input]) # add the data at the end
return links
else: # get action, don't get user input
return links
else:
return ["get", "default", None]
request = ["get", "default", None]
while True:
# "server"-side computation
state_representation, links = handle_request(*request)
# "client"-side computation
request = render_and_get_input(state_representation, links)