-
Notifications
You must be signed in to change notification settings - Fork 0
/
flask_map.py
146 lines (112 loc) · 4.11 KB
/
flask_map.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
"""
A simple Flask website that displays a map of the user's city and indicates
each intersection where a street named after a president intersects with a
numbered street whose number is that president's number - e.g. '1st and
Washington', '2nd and Adams', etc.
"""
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
from flask.ext.cache import Cache
import json
import logging
import argparse # For the vocabulary list
import sys
###
# Our own modules
###
import geocoder
###
# Globals
###
import CONFIG
from presidents import PRESIDENTS
CACHESIZE = CONFIG.CACHESIZE
app = flask.Flask(__name__)
cache = Cache(app, config={"CACHE_TYPE":"filesystem",
"CACHE_THRESHOLD":CACHESIZE,
"CACHE_DIR":".flaskCache",
"CACHE_DEFAULT_TIMEOUT":1000})
app.secret_key = CONFIG.COOKIE_KEY # Should allow using session variables
@cache.memoize() # Cached so we can avoid the 4+ second API lookup time
def geocode_presidents(town):
"""
Returns a list of all intersections where a numbered street crosses a street
named after the corresponding president ("1st and Washington", etc.)
Each item in the resulting list is a tuple, with item[0] holding the name
of the intersection ("1st and Washington"), and item[1] holding a tuple
containing the latitude and longitude of the intersection.
Args:
town is typically formatted like "City, State, Country", but Google will
accept other formats
"""
points = []
for i in PRESIDENTS:
streets = geocoder.get_ordinal_string(i) + " and " + PRESIDENTS[i]
intersections = geocoder.geocode_intersection(streets, town)
for point in intersections:
points.append((streets, point))
return points
###
# Pages
###
@app.route("/")
@app.route("/index")
def index():
return flask.render_template('presidents.html')
###############
# AJAX request handlers
# These return JSON, rather than rendering pages.
###############
@app.route("/_getPoints")
def getPoints():
"""
The user gave us their city. We must return a list of points marking
places where a numbered street intersects a street named after the president
corresponding to that number (e.g. 1st and Washington)
The points are formatted as tuples, where point[0] is a description of the
intersection ("1st and Washington"), and point[1] is a tuple containing the
latitude and longitude of the point.
"""
app.logger.debug("Entering getPoints")
rslt = {}
points = []
user_city = request.args.get("city", type=str)
points = geocode_presidents(user_city)
rslt["points"] = points
rslt["did_find_points"] = bool(points) # Empty lists are False
return jsonify(result=rslt)
###################
# Error handlers
###################
@app.errorhandler(404)
def error_404(e):
app.logger.warning("++ 404 error: {}".format(e))
return 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 render_template('500.html'), 500
@app.errorhandler(403)
def error_403(e):
app.logger.warning("++ 403 error: {}".format(e))
return 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.
#FIXME: Debug cgi interface
app.debug=False