11import asyncio
2+ import importlib
3+ from typing import Callable , Any
24
35import tornado
46import tornado .web
57import tornado .log
8+ import yaml
69
710from dashipy .context import Context
8- from dashipy .panel import get_panel
911from dashipy import __version__
1012
1113
12- class RootHandler (tornado .web .RequestHandler ):
13- def get (self ):
14- self .set_header ("Content-Type" , "text/plain" )
15- self .write (f"dashi-server { __version__ } " )
16-
17-
18- class PanelHandler (tornado .web .RequestHandler ):
14+ class RequestHandler (tornado .web .RequestHandler ):
1915
2016 def set_default_headers (self ):
2117 self .set_header ("Access-Control-Allow-Origin" , "*" )
@@ -26,30 +22,74 @@ def set_default_headers(self):
2622 "authorization,content-type" ,
2723 )
2824
25+
26+ class RootHandler (RequestHandler ):
2927 def get (self ):
30- context : Context = self .settings ["context" ]
31- panel = get_panel (context )
28+ self .set_header ("Content-Type" , "text/plain" )
29+ self .write (f"dashi-server { __version__ } " )
30+
31+
32+ class PanelsHandler (RequestHandler ):
33+
34+ # GET /panels
35+ def get (self ):
36+ panels : dict [str , Callable ] = self .settings ["panels" ]
3237 self .set_header ("Content-Type" , "text/json" )
33- self .write (panel . to_dict () )
38+ self .write ({ "panels" : list ( panels . keys ())} )
3439
35- def post (self ):
36- context : Context = self .settings ["context" ]
40+
41+ class PanelRendererHandler (RequestHandler ):
42+ # GET /panels/{panel_id}
43+ def get (self , panel_id : str ):
44+ self .render_panel (panel_id , {})
45+
46+ # POST /panels/{panel_id}
47+ def post (self , panel_id : str ):
3748 event = tornado .escape .json_decode (self .request .body )
38- print (event )
39- event_data = event .get ("eventData" ) or {}
40- panel = get_panel (context , ** event_data )
41- self .set_header ("Content-Type" , "text/json" )
42- self .write (panel .to_dict ())
49+ panel_props = event .get ("eventData" ) or {}
50+ self .render_panel (panel_id , panel_props )
51+
52+ def render_panel (self , panel_id : str , panel_props : dict [str , Any ]):
53+ context : Context = self .settings ["context" ]
54+ panels : dict [str , Callable ] = self .settings ["panels" ]
55+ panel_renderer = panels .get (panel_id )
56+ if panel_renderer is not None :
57+ self .set_header ("Content-Type" , "text/json" )
58+ self .write (panel_renderer (context , ** panel_props ).to_dict ())
59+ else :
60+ self .set_status (404 , f"panel not found: { panel_props } " )
4361
4462
4563def make_app ():
64+ # Read config
65+ with open ("my-config.yaml" ) as f :
66+ server_config = yaml .load (f , yaml .SafeLoader )
67+
68+ # Parse panel renderers
69+ panels : dict [str , Callable ] = {}
70+ for panel_ref in server_config .get ("panels" , []):
71+ try :
72+ module_name , function_name = panel_ref .rsplit ("." , maxsplit = 2 )
73+ except (ValueError , AttributeError ):
74+ raise TypeError (f"panel renderer syntax error: { panel_ref !r} " )
75+ module = importlib .import_module (module_name )
76+ render_function = getattr (module , function_name )
77+ if not callable (render_function ):
78+ raise TypeError (
79+ f"panel renderer { panel_ref !r} does not refer to a callable"
80+ )
81+ panels [panel_ref .replace ("." , "-" ).replace ("_" , "-" ).lower ()] = render_function
82+
83+ # Create app
4684 app = tornado .web .Application (
4785 [
4886 (r"/" , RootHandler ),
49- (r"/panel" , PanelHandler ),
87+ (r"/panels" , PanelsHandler ),
88+ (r"/panels/([a-z0-9-]+)" , PanelRendererHandler ),
5089 ]
5190 )
5291 app .settings ["context" ] = Context ()
92+ app .settings ["panels" ] = panels
5393 return app
5494
5595
@@ -58,7 +98,7 @@ async def main():
5898 port = 8888
5999 app = make_app ()
60100 app .listen (port )
61- print (f"Listening http://127.0.0.1:{ port } ..." )
101+ print (f"Listening on http://127.0.0.1:{ port } ..." )
62102 shutdown_event = asyncio .Event ()
63103 await shutdown_event .wait ()
64104
0 commit comments