forked from codeforamerica/US-Census-Area-API
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.py
121 lines (91 loc) · 3.59 KB
/
app.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
from sys import stderr
from os import environ
from urlparse import urlparse
from StringIO import StringIO
from zipfile import ZipFile, ZIP_DEFLATED
from time import time
from flask import Flask
from flask import request
from flask import Response
from flask import render_template
from osgeo import ogr
from geo import get_intersecting_features
from util import json_encode, bool
from census import census_url, get_features as census_features
app = Flask(__name__)
def is_census_datasource(environ):
''' Return true if the environment specifies the U.S. Census datasource.
'''
return environ.get('GEO_DATASOURCE', None) == census_url
def get_datasource(environ):
''' Return an environment-appropriate datasource.
For local data, this will be an OGR Datasource object.
'''
if is_census_datasource(environ):
# Use the value of the environment variable directly,
datasource = environ['GEO_DATASOURCE']
else:
# Or just open datasource.shp with OGR.
datasource = ogr.Open('datasource.shp')
return datasource
@app.route('/')
def hello():
host_port = urlparse(request.base_url).netloc.encode('utf-8')
is_downloadable = not is_census_datasource(environ)
is_us_census = is_census_datasource(environ)
return render_template('index.html', **locals())
@app.route('/.well-known/status')
def status():
datasource = get_datasource(environ)
status = {
'status': 'ok' if bool(datasource) else 'Bad datasource: %s' % repr(datasource),
'updated': int(time()),
'dependencies': [],
'resources': {}
}
body = json_encode(status)
return Response(body, headers={'Content-type': 'application/json',
'Access-Control-Allow-Origin': '*'})
@app.route("/areas")
def areas():
''' Retrieve geographic areas.
'''
is_census = is_census_datasource(environ)
lat = float(request.args['lat'])
lon = float(request.args['lon'])
include_geom = bool(request.args.get('include_geom', True))
json_callback = request.args.get('callback', None)
layer_names = is_census and request.args.get('layers', '')
layer_names = layer_names and set(layer_names.split(','))
# This. Is. Python.
ogr.UseExceptions()
point = ogr.Geometry(wkt='POINT(%f %f)' % (lon, lat))
if is_census:
features = census_features(point, include_geom, layer_names)
else:
datasource = get_datasource(environ)
features = get_intersecting_features(datasource, point, include_geom)
geojson = dict(type='FeatureCollection', features=features)
body, mime = json_encode(geojson), 'application/json'
if json_callback:
body = '%s(%s);\n' % (json_callback, body)
mime = 'text/javascript'
return Response(body, headers={'Content-type': mime, 'Access-Control-Allow-Origin': '*'})
@app.errorhandler(404)
def error_404(error):
return render_template('error.html', error=str(error))
@app.route('/datasource.zip')
def download_zip():
if is_census_datasource(environ):
error = "Can't download all of " + census_url
return Response(render_template('error.html', error=error), status=404)
buffer = StringIO()
archive = ZipFile(buffer, 'w', ZIP_DEFLATED)
archive.write('datasource.shp')
archive.write('datasource.shx')
archive.write('datasource.dbf')
archive.write('datasource.prj')
archive.close()
return Response(buffer.getvalue(), headers={'Content-Type': 'application/zip'})
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)