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