11import threading
22from datetime import timedelta
3+ from perspective import Table as Table_ , View as View_
34from typing import Dict , Optional , Union
45
56import csp
67from csp import ts
8+ from csp .impl .perspective_common import (
9+ date_to_perspective ,
10+ datetime_to_perspective ,
11+ is_perspective3 ,
12+ perspective_type_map ,
13+ )
714from csp .impl .wiring .delayed_node import DelayedNodeWrapperDef
815
916try :
1421 raise ImportError ("perspective adapter requires tornado package" )
1522
1623
17- try :
18- from perspective import PerspectiveManager , Table as Table_ , View as View_ , __version__ , set_threadpool_size
19-
20- MAJOR , MINOR , PATCH = map (int , __version__ .split ("." ))
21- if (MAJOR , MINOR , PATCH ) < (0 , 6 , 2 ):
22- raise ImportError ("perspective adapter requires 0.6.2 or greater of the perspective-python package" )
23- except ImportError :
24- raise ImportError ("perspective adapter requires 0.6.2 or greater of the perspective-python package" )
24+ _PERSPECTIVE_3 = is_perspective3 ()
25+ if _PERSPECTIVE_3 :
26+ from perspective import Server
27+ else :
28+ from perspective import PerspectiveManager
2529
2630
2731# Run perspective update in a separate tornado loop
28- def perspective_thread (manager ):
32+ def perspective_thread (client ):
2933 loop = tornado .ioloop .IOLoop ()
30- manager .set_loop_callback (loop .add_callback )
34+ client .set_loop_callback (loop .add_callback )
3135 loop .start ()
3236
3337
@@ -38,12 +42,25 @@ def _apply_updates(table: object, data: {str: ts[object]}, throttle: timedelta):
3842
3943 with csp .state ():
4044 s_buffer = []
45+ s_datetime_cols = set ()
46+ s_date_cols = set ()
4147
4248 with csp .start ():
4349 csp .schedule_alarm (alarm , throttle , True )
50+ if _PERSPECTIVE_3 :
51+ s_datetime_cols = set ([c for c , t in table .schema ().items () if t == "datetime" ])
52+ s_date_cols = set ([c for c , t in table .schema ().items () if t == "date" ])
4453
4554 if csp .ticked (data ):
46- s_buffer .append (dict (data .tickeditems ()))
55+ row = dict (data .tickeditems ())
56+ if _PERSPECTIVE_3 :
57+ for col , value in row .items ():
58+ if col in s_datetime_cols :
59+ row [col ] = datetime_to_perspective (row [col ])
60+ if col in s_date_cols :
61+ row [col ] = date_to_perspective (row [col ])
62+
63+ s_buffer .append (row )
4764
4865 if csp .ticked (alarm ):
4966 if len (s_buffer ) > 0 :
@@ -54,19 +71,25 @@ def _apply_updates(table: object, data: {str: ts[object]}, throttle: timedelta):
5471
5572
5673@csp .node
57- def _launch_application (port : int , manager : object , stub : ts [object ]):
74+ def _launch_application (port : int , server : object , stub : ts [object ]):
5875 with csp .state ():
5976 s_app = None
6077 s_ioloop = None
6178 s_iothread = None
6279
6380 with csp .start ():
64- from perspective import PerspectiveTornadoHandler
81+ if _PERSPECTIVE_3 :
82+ from perspective .handlers .tornado import PerspectiveTornadoHandler
6583
84+ handler_args = {"perspective_server" : server , "check_origin" : True }
85+ else :
86+ from perspective import PerspectiveTornadoHandler
87+
88+ handler_args = {"manager" : server , "check_origin" : True }
6689 s_app = tornado .web .Application (
6790 [
6891 # create a websocket endpoint that the client Javascript can access
69- (r"/websocket" , PerspectiveTornadoHandler , { "manager" : manager , "check_origin" : True } )
92+ (r"/websocket" , PerspectiveTornadoHandler , handler_args )
7093 ],
7194 websocket_ping_interval = 15 ,
7295 )
@@ -196,21 +219,34 @@ def create_table(self, name, limit=None, index=None):
196219 return table
197220
198221 def _instantiate (self ):
199- set_threadpool_size (self ._threadpool_size )
200-
201- manager = PerspectiveManager ()
222+ if _PERSPECTIVE_3 :
223+ server = Server ()
224+ client = server .new_local_client ()
225+ thread = threading .Thread (target = perspective_thread , kwargs = dict (client = client ))
226+ else :
227+ from perspective import set_threadpool_size
202228
203- thread = threading .Thread (target = perspective_thread , kwargs = dict (manager = manager ))
229+ set_threadpool_size (self ._threadpool_size )
230+ manager = PerspectiveManager ()
231+ thread = threading .Thread (target = perspective_thread , kwargs = dict (manager = manager ))
204232 thread .daemon = True
205233 thread .start ()
206234
207235 for table_name , table in self ._tables .items ():
208236 schema = {
209237 k : v .tstype .typ if not issubclass (v .tstype .typ , csp .Enum ) else str for k , v in table .columns .items ()
210238 }
211- ptable = Table (schema , limit = table .limit , index = table .index )
212- manager .host_table (table_name , ptable )
239+ if _PERSPECTIVE_3 :
240+ psp_type_map = perspective_type_map ()
241+ schema = {col : psp_type_map .get (typ , typ ) for col , typ in schema .items ()}
242+ ptable = client .table (schema , name = table_name , limit = table .limit , index = table .index )
243+ else :
244+ ptable = Table (schema , limit = table .limit , index = table .index )
245+ manager .host_table (table_name , ptable )
213246
214247 _apply_updates (ptable , table .columns , self ._throttle )
215248
216- _launch_application (self ._port , manager , csp .const ("stub" ))
249+ if _PERSPECTIVE_3 :
250+ _launch_application (self ._port , server , csp .const ("stub" ))
251+ else :
252+ _launch_application (self ._port , manager , csp .const ("stub" ))
0 commit comments