comparison globalneighbors/web.py @ 0:5dba84370182

initial commit; half-working prototype
author Jeff Hammel <k0scist@gmail.com>
date Sat, 24 Jun 2017 12:03:39 -0700
parents
children 1b94f3bf97e5
comparison
equal deleted inserted replaced
-1:000000000000 0:5dba84370182
1 #!/usr/bin/env python
2
3 """
4 web handler for GlobalNeighbors
5 """
6
7 # imports
8 import argparse
9 import json
10 import sys
11 import time
12 from webob import Request, Response, exc
13 from wsgiref import simple_server
14 from .locations import locations
15 from .locations import city_dict
16 from .read import read_cities
17 from .read import read_city_list
18 from .schema import fields
19 from .schema import name
20
21
22 class Handler(object):
23 """base class for HTTP handler"""
24
25 def __call__(self, environ, start_response):
26 request = Request(environ)
27 method = getattr(self, request.method, None)
28 response = None
29 if method is not None:
30 response = method(request)
31 if response is None:
32 response = exc.HTTPNotFound()
33 return response(environ, start_response)
34
35
36 class CitiesHandler(Handler):
37 """cities ReST API"""
38
39 content_type = 'application/json'
40
41 def __init__(self, locations, cities):
42 self.locations = locations
43 self._cities = cities
44
45
46 def cities(self, startswith=None):
47 """return list of cities"""
48
49 if startswith:
50 return sorted([i[name] for i in self._cities
51 if i[name].startswith(startswith)])
52 else:
53 return sorted([i[name] for i in self._cities])
54
55 def GET(self, request):
56 return Response(content_type=self.content_type,
57 body=json.dumps(self.cities(
58 startswith=request.GET.get('q'))))
59
60
61 class GlobalHandler(Handler):
62 """WSGI HTTP Handler"""
63
64 content_type = 'text/plain'
65
66 def __init__(self, datafile):
67 self.datafile = datafile
68
69 # parse data
70 self.cities = read_city_list(self.datafile,
71 fields=fields)
72 self.locations = locations(self.cities)
73
74 # TODO: declare handlers
75 self.handlers = {'/cities':
76 CitiesHandler(self.locations,
77 self.cities)}
78
79
80 def GET(self, request):
81 if request.path_info in ('', '/'):
82 # Landing page
83 return Response(content_type=self.content_type,
84 body="""Global Neighbors
85 Serving {} cities""".format(len(self.cities)))
86 else:
87 handler = self.handlers.get(request.path_info)
88 if handler:
89 return request.get_response(handler)
90
91
92
93 def main(args=sys.argv[1:]):
94 """CLI"""
95
96 # parse command line
97 parser = argparse.ArgumentParser(description=__doc__)
98 parser.add_argument('cities',
99 help="cities1000 data file")
100 parser.add_argument('-p', '--port', dest='port',
101 type=int, default=8080,
102 help="port to serve on")
103 parser.add_argument('--hostname', dest='hostname',
104 default='localhost',
105 help="host name [DEFAULT: %(default)]")
106 options = parser.parse_args(args)
107
108 # instantiate WSGI handler
109 app = GlobalHandler(datafile=options.cities)
110
111 # serve it (Warning! Single threaded!)
112 server = simple_server.make_server(host='0.0.0.0',
113 port=options.port,
114 app=app)
115 try:
116 print ("Serving on http://{hostname}:{port}/".format(**options.__dict__))
117 server.serve_forever()
118 except KeyboardInterrupt:
119 pass
120
121
122 if __name__ == '__main__':
123 main()
124