# Simple REST server that takes commands in JSON
# TODO: use some other web framework (Tornado?)

import cgi, json, BaseHTTPServer
import central_planner

class Server:
    def __init__(self, host = '', port = 8081):
        self.__urls = []
        self.__handlers = {}
        self.__host = host
        self.__port = 8081

        self.__scheduler = central_planner.CentralPlannerScheduler()

        def json_input(args):
            # TODO: support arbitrary types, not just strings
            data = json.loads(args.get('data', '{}'))
            kv = {}
            for k, v in data.iteritems():
                kv[str(k)] = str(v) # The problem is that otherwise we have problem with unicode casting

            return kv

        def json_output(result, handler):
            page = json.dumps(result)

            handler.send_response(200)
            handler.send_header('content-type', 'text/html')
            handler.end_headers()
            handler.wfile.write(page)

        def svg_output(result, handler):
            handler.send_response(200)
            handler.send_header('content-type', 'image/svg+xml')
            handler.end_headers()
            handler.wfile.write(result)

        self.__handlers = {'/api/task': (self.__scheduler.add_task, json_input, json_output),
                           '/api/dep': (self.__scheduler.add_dep, json_input, json_output),
                           '/api/work': (self.__scheduler.get_work, json_input, json_output),
                           '/api/status': (self.__scheduler.status, json_input, json_output),
                           '/api/ping': (self.__scheduler.ping, json_input, json_output),
                           '/draw': (self.__scheduler.draw, json_input, svg_output), # TODO: duck typing, assumes a Central Planner
                           '/': (self.__scheduler.draw, json_input, svg_output)} # just an alias

    def process(self, cmd, args, handler):
        f, input_reader, output_writer = self.__handlers[str(cmd)]
        input = input_reader(args)
        result = f(**input)
        output = output_writer(result, handler)
        return output

    def run(self):
        server = self
        class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
            def do_GET(self):
                p = self.path

                d = p.split('?')
                if len(d) == 2:
                    cmd, tmp = d
                    args = {}
                    for k, v in cgi.parse_qs(tmp).iteritems():
                        args[k] = v[0]

                else:
                    cmd, args = p, {}

                server.process(cmd, args, self)

        httpd = BaseHTTPServer.HTTPServer((self.__host, self.__port), Handler)
        httpd.serve_forever()
        
if __name__ == "__main__":
    s = Server()
    s.run()


@@ -46,505 +46,133 @@
 SON%0A
-# TODO: use some other web framework (Tornado?)%0A%0Aimport cgi, json, BaseHTTPServer%0Aimport central_planner%0A%0Aclass Server:%0A    def __init__(self, host = '', port = 8081):%0A        self.__urls = %5B%5D%0A        self.__handlers = %7B%7D%0A        self.__host = host%0A        self.__port = 8081%0A%0A        self.__scheduler = central_planner.CentralPlannerScheduler()%0A%0A        def json_input(args):%0A            # TODO: support arbitrary types, not just strings%0A            data = json.loads(args.get('data', '%7B%7D'))%0A    
+%0Aimport cherrypy, json%0Aimport central_planner%0A%0Adef json_wrapped(f):%0A    def f_wrapped(data):%0A        data = json.loads(data)%0A
     
@@ -183,36 +183,32 @@
 kv = %7B%7D%0A        
-    
 for k, v in data
@@ -233,20 +233,16 @@
         
-    
 kv%5Bstr(k
@@ -259,29 +259,9 @@
 ) # 
-The problem is that o
+O
 ther
@@ -302,17 +302,16 @@
 casting%0A
-%0A
         
@@ -318,60 +318,33 @@
     
-return kv%0A%0A        def json_output(result, handler):
+%0A        result = f(**kv)
 %0A   
@@ -352,18 +352,23 @@
     
+%0A
     
-page =
+    return
  jso
@@ -387,2016 +387,801 @@
 lt)%0A
-%0A            handler.send_response(200)%0A            handler.send_header('content-type', 'text/html')%0A            handler.end_headers()%0A            handler.wfile.write(page)%0A%0A  
+    return f_wrapped%0A%0Aclass Server(object):%0A
     
-  
 def 
-svg_output(result, handler):%0A            handler.send_response(200)%0A            handler.send_header('content-type', 'image/svg+xml')%0A            handler.end_headers()%0A            handler.wfile.write(result)%0A%0A        self.__handlers = %7B'/api/
+__init__(self):%0A        sch = central_planner.CentralPlannerScheduler()%0A%0A        class API(object): pass%0A        self.api = API()%0A%0A        self.api.
 task
-': (self.__scheduler.add_task, json_input, json_output),%0A                           '/api/dep': (self.__scheduler.add_dep, json_input, json_output),%0A                           '/api/
+ = cherrypy.expose(json_wrapped(sch.add_task))%0A        self.api.dep  = cherrypy.expose(json_wrapped(sch.add_dep))%0A        self.api.
 work
-': (self.__scheduler.get_work, json_input, json_output),%0A                           '/api/status': (self.__scheduler.status, json_input, json_output),%0A                           '/api/
+ = cherrypy.expose(json_wrapped(sch.get_work))%0A        self.api.
 ping
-': (self.__scheduler.ping, json_input, json_output),%0A                           '/draw': (self.__scheduler.draw, json_input, svg_output), # TODO: duck typing, assumes a Central Planner%0A                           '/': (self.__scheduler.draw, json_input, svg_output)%7D # just an alias%0A%0A    def process(self, cmd, args, handler):%0A        f, input_reader, output_writer = self.__handlers%5Bstr(cmd)%5D%0A        input = input_reader(args)%0A        result = f(**input)%0A        output = output_writer(result, handler)%0A        return output%0A%0A    def run(self):%0A        server = self%0A        class Handler(BaseHTTPServer.BaseHTTPRequestHandler):%0A            def do_GET(self):%0A                p = self.path%0A%0A                d = p.split('?')%0A                if len(d) == 2:%0A                    cmd, tmp = d%0A                    args = %7B%7D%0A                    for k, v in cgi.parse_qs(tmp).iteritems():%0A                        args%5Bk%5D = v%5B0%5D%0A%0A                else:%0A                    cmd, args = p, %7B%7D%0A%0A                server.process(cmd, args, self)%0A%0A        httpd = BaseHTTPServer.HTTPServer((self.__host, self.__port), Handler)%0A        httpd.serve_forever()%0A        %0Aif __name__ == %22__main__%22:%0A    s = Server()%0A    s.run(
+ = cherrypy.expose(json_wrapped(sch.ping))%0A        self.api.status = cherrypy.expose(json_wrapped(sch.status))%0A        self.draw = cherrypy.expose(lambda: sch.draw())%0A        self.index = self.draw%0A%0Aif __name__ == %22__main__%22:%0A    s = Server()%0A    cherrypy.config.update(%7B'server.socket_host': '0.0.0.0',%0A                            'server.socket_port': 8081,%7D)%0A    cherrypy.quickstart(s
 )%0A%0A

replace BaseHTTPServer with CherryPy