Mercurial > hg > WSGraph
annotate wsgraph/web.py @ 15:ee45f44394a0
i need a name, Bastian
| author | Jeff Hammel <jhammel@mozilla.com> |
|---|---|
| date | Mon, 10 Dec 2012 17:33:44 -0800 |
| parents | 3d0430390e72 |
| children | 569a5d93b8e3 |
| rev | line source |
|---|---|
| 0 | 1 #!/usr/bin/env python |
| 2 | |
| 3 """ | |
| 4 web handler for WSGraph | |
| 5 """ | |
| 6 | |
| 7 import json | |
|
12
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
8 import sys |
| 0 | 9 from webob import Request, Response, exc |
| 10 | |
| 5 | 11 # rank constants |
| 4 | 12 GRAPH = 0 |
| 13 NODE = 1 | |
| 14 EDGE = 2 | |
| 15 | |
| 5 | 16 # XXX stubbing hacks |
| 7 | 17 class JSONformatter(object): |
| 18 def __init__(self, sort_keys=True): | |
| 19 self.sort_keys = sort_keys | |
| 20 | |
| 21 def format(self, _object): | |
| 22 return json.dumps(graph.node(node), sort_keys=self.sort_keys) | |
| 23 | |
| 24 def node(self, node, graph, request): | |
| 25 return Response(body=self.format(graph.node(node))) | |
| 26 | |
| 6 | 27 def JSONFormatter(node, graph, request): |
| 28 return json.dumps(graph.node(node), sort_keys=True) | |
| 29 def JSONGraphFormatter(graph, request): | |
| 0 | 30 return json.dumps({'nodes': graph.nodes(), |
| 31 'edges': graph.edges()}, | |
| 32 sort_keys=True) | |
| 33 | |
| 34 class Dispatcher(object): | |
| 35 | |
| 36 def __init__(self, graph, | |
| 5 | 37 graph_formatters=None, |
| 38 node_formatters=None, | |
| 39 edge_formatters=None, | |
| 0 | 40 require_auth=False): |
| 41 self.graph = graph | |
| 42 self.require_auth = require_auth | |
| 5 | 43 |
| 44 # use JSON formatter by default | |
| 45 if graph_formatters is None: | |
| 46 graph_formatters = {None: JSONGraphFormatter} | |
|
13
7459702bf574
mostly spacing fix + comment
Jeff Hammel <jhammel@mozilla.com>
parents:
12
diff
changeset
|
47 if node_formatters is None: |
| 5 | 48 node_formatters = {None: JSONFormatter} |
|
13
7459702bf574
mostly spacing fix + comment
Jeff Hammel <jhammel@mozilla.com>
parents:
12
diff
changeset
|
49 if edge_formatters is None: |
| 5 | 50 edge_formatters = {None: JSONFormatter} |
| 51 | |
|
13
7459702bf574
mostly spacing fix + comment
Jeff Hammel <jhammel@mozilla.com>
parents:
12
diff
changeset
|
52 # view formatters |
| 5 | 53 self.formatters = {GRAPH: graph_formatters, |
| 54 NODE: node_formatters, | |
| 55 EDGE: edge_formatters} | |
| 56 for key, value in formatters.items(): | |
| 57 # ensure default formatter | |
| 58 assert None in value | |
| 0 | 59 |
| 3 | 60 self.methods = dict([(i, getattr(self, i)) |
| 61 for i in dir(self) | |
| 62 if i.isupper()]) | |
| 63 | |
| 0 | 64 def __call__(self, environ, start_response): |
| 65 request = Request(environ) | |
| 3 | 66 method = self.methods.get(request.method) |
| 67 if method is None: | |
| 68 return exc.HTTPMethodNotAllowed()(environ, start_response) | |
| 69 response = method(request) | |
| 0 | 70 return response(environ, start_response) |
| 71 | |
| 72 @staticmethod | |
| 5 | 73 def path_segments(path): |
| 74 """split a path into segments""" | |
| 75 segments = path.strip('/').split('/') | |
| 76 if segments == ['']: | |
| 77 segments = [] | |
| 78 return segments | |
| 0 | 79 |
| 80 # HTTP methods | |
| 81 | |
| 82 def GET(self, request): | |
|
2
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
83 """ |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
84 respond to a GET request |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
85 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
86 Formatters are keyed off of |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
87 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
88 formatters = {0: { |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
89 } |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
90 |
| 4 | 91 A graph formatter takes the following arguments: |
| 92 | |
| 6 | 93 def sample_graph_formatter(graph, request): |
| 94 | |
| 95 A node formatter takes the following arguments: | |
| 96 | |
| 97 def sample_node_formatter(node, graph, request): | |
| 98 | |
| 99 An edge formatter takes the following arguments: | |
| 100 | |
| 101 def sample_edge_formatter(edge, graph, request): | |
| 4 | 102 |
|
2
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
103 API: |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
104 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
105 ?format=<format> |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
106 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
107 """ |
| 0 | 108 |
| 7 | 109 # get resource requestor |
| 5 | 110 segments = self.path_segments(request.path_info) |
|
12
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
111 rank = len(segments) |
|
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
112 if rank not in (0,1,2): |
| 4 | 113 return exc.HTTPNotFound() |
| 0 | 114 |
| 7 | 115 |
| 116 # is resource in the graph? [TODO] | |
|
12
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
117 if (rank == EDGE) or (rank == NODE): |
|
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
118 if tuple(segments) not in self.graph: |
| 14 | 119 return exc.HTTPNotFound() |
| 7 | 120 |
| 0 | 121 # formatter |
| 122 formatter = self.formatters[len(segments)] | |
| 123 return Response(content_type='text/plain', | |
| 124 body="WSGraph") | |
| 125 | |
| 126 def POST(self, request): | |
|
2
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
127 """ |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
128 respond to a POST request |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
129 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
130 API: |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
131 |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
132 ?update : |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
133 """ |
|
7a3b21cafc00
start to sketch out REST API
Jeff Hammel <jhammel@mozilla.com>
parents:
0
diff
changeset
|
134 |
| 4 | 135 return exc.HTTPSeeOther(location='/') # TODO: /path/to/self |
| 0 | 136 |
| 137 def HEAD(self, request): | |
| 138 """respond to a HEAD request""" | |
| 139 raise NotImplementedError | |
| 140 | |
| 3 | 141 def OPTIONS(self, request): |
| 4 | 142 return Response() # TODO: Allow=', '.join(self.methods); Content-Length=0 |
| 3 | 143 |
| 0 | 144 |
|
12
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
145 def main(args=sys.argv[1:]): |
|
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
146 """example web server""" |
| 3 | 147 |
| 0 | 148 # imports |
| 149 from wsgiref import simple_server | |
| 3 | 150 from model import MemoryCache |
| 151 from optparse import OptionParser | |
| 0 | 152 |
| 3 | 153 # parse command line options |
| 154 parser = OptionParser() | |
| 155 parser.add_option('-p', '--port', type='int', default=8080, | |
| 156 help="port to serve on") | |
| 157 options, args = parser.parse_args() | |
| 158 | |
| 159 # example model | |
| 0 | 160 graph = MemoryCache() |
| 161 | |
| 3 | 162 # WSGI app |
| 0 | 163 app = Dispatcher(graph=graph) |
| 3 | 164 server = simple_server.make_server(host='0.0.0.0', port=options.port, app=app) |
| 165 print 'http://localhost:%s/' % options.port | |
| 0 | 166 server.serve_forever() |
| 167 | |
|
12
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
168 if __name__ == '__main__': |
|
421d5119e324
reluctantly make this a CLI entry point
Jeff Hammel <jhammel@mozilla.com>
parents:
7
diff
changeset
|
169 main() |
