1+ #!/usr/bin/python3
2+ # Test Server for PythonScript
3+ # by Brett Hartshorn - copyright 2013
4+ # License: PSFLv2 - http://www.python.org/psf/license/
5+ # Requires: Python3 and Tornado
6+
7+ try :
8+ import tornado
9+ except ImportError :
10+ print ('ERROR: Tornado is not installed' )
11+ print ('download Tornado from - http://www.tornadoweb.org/en/stable/' )
12+ raise SystemExit
13+
14+ import tornado .ioloop
15+ import tornado .web
16+ import os , subprocess
17+
18+ PATHS = dict (
19+ webroot = os .path .dirname (os .path .abspath (__file__ )),
20+ pythonscript = os .path .abspath ('../pythonscript' ),
21+ bindings = os .path .abspath ('../bindings' ),
22+ closure = os .path .expanduser ( '~/closure-compiler/compiler.jar' ),
23+ runtime = os .path .abspath ('../pythonscript.js' ),
24+ )
25+
26+
27+ def python_to_pythonjs ( src ):
28+ p = subprocess .Popen (
29+ ['python2' , os .path .join ( PATHS ['pythonscript' ], 'python_to_pythonjs.py' )],
30+ stdin = subprocess .PIPE ,
31+ stdout = subprocess .PIPE
32+ )
33+ stdout , stderr = p .communicate ( src .encode ('utf-8' ) )
34+ return stdout .decode ('utf-8' )
35+
36+ def pythonjs_to_javascript ( src , closure_compiler = False ):
37+ p = subprocess .Popen (
38+ ['python2' , os .path .join ( PATHS ['pythonscript' ],'pythonjs.py' )],
39+ stdin = subprocess .PIPE ,
40+ stdout = subprocess .PIPE
41+ )
42+ stdout , stderr = p .communicate ( src .encode ('utf-8' ) )
43+ a = stdout .decode ('utf-8' )
44+
45+ if closure_compiler and os .path .isfile ( PATHS ['closure' ] ):
46+ x = '/tmp/input.js' ; y = '/tmp/output.js'
47+ f = open (x , 'wb' ); f .write ( a .encode ('utf-8' ) ); f .close ()
48+ subprocess .call ( ['java' , '-jar' , PATHS ['closure' ], '--compilation_level' , 'ADVANCED_OPTIMIZATIONS' , '--js' , x , '--js_output_file' , y ] )
49+ f = open (y , 'rb' ); a = f .read ().decode ('utf-8' ); f .close ()
50+
51+ return a
52+
53+ def python_to_javascript ( src , closure_compiler = False ):
54+ a = python_to_pythonjs ( src )
55+ return pythonjs_to_javascript ( a , closure_compiler = closure_compiler )
56+
57+
58+
59+ #########################################################
60+ def get_main_page ():
61+ root = PATHS ['webroot' ]
62+ r = ['<html><head><title>index</title></head><body>' ]
63+ r .append ( '<ul>' )
64+ for name in os .listdir ( root ):
65+ if name == os .path .split (__file__ )[- 1 ]: continue
66+ path = os .path .join ( root , name )
67+ if os .path .isfile ( path ):
68+ r .append ( '<a href="%s"><li>%s</li></a>' % (name ,name ) )
69+ r .append ('</ul>' )
70+ r .append ('</body></html>' )
71+ return '' .join (r )
72+
73+
74+ def convert_python_html_document ( data ):
75+ '''
76+ rewrites html document, converts python scripts into javascript.
77+ example:
78+ <script type="text/python" closure="true">
79+ print("hello world")
80+ </script>
81+ '''
82+ doc = list ()
83+ script = None
84+ use_closure = False
85+ for line in data .splitlines ():
86+ if line .strip ().startswith ('<script' ) and 'type="text/python"' in line :
87+ if 'closure="true"' in line .lower (): use_closure = True
88+ else : use_closure = False
89+ doc .append ( '<script type="text/javascript">' )
90+ script = list ()
91+
92+ elif line .strip () == '</script>' :
93+ if script :
94+ src = '\n ' .join ( script )
95+ js = python_to_javascript ( src , closure_compiler = use_closure )
96+ doc .append ( js )
97+ doc .append ( line )
98+ script = None
99+
100+ elif isinstance ( script , list ):
101+ script .append ( line )
102+
103+ else :
104+ doc .append ( line )
105+
106+ return '\n ' .join ( doc )
107+
108+ class MainHandler ( tornado .web .RequestHandler ):
109+ def get (self , path = None ):
110+ print ('path' , path )
111+ if not path :
112+ self .write ( get_main_page () )
113+ elif path == 'pythonscript.js' :
114+ data = open ( PATHS ['runtime' ], 'rb' ).read ()
115+ self .set_header ("Content-Type" , "text/javascript; charset=utf-8" )
116+ self .set_header ("Content-Length" , len (data ))
117+ self .write (data )
118+ elif path .startswith ('bindings/' ):
119+ name = path .split ('/' )[- 1 ]
120+ local_path = os .path .join ( PATHS ['bindings' ], name )
121+
122+ if os .path .isfile ( local_path ):
123+ data = open (local_path , 'rb' ).read ()
124+ else :
125+ raise tornado .web .HTTPError (404 )
126+
127+ if path .endswith ('.py' ):
128+ data = python_to_javascript ( data .decode ('utf-8' ), closure_compiler = False )
129+
130+ self .set_header ("Content-Type" , "text/javascript; charset=utf-8" )
131+ self .set_header ("Content-Length" , len (data ))
132+ self .write ( data )
133+
134+ else :
135+ local_path = os .path .join ( PATHS ['webroot' ], path )
136+ if os .path .isfile ( local_path ):
137+ data = open (local_path , 'rb' ).read ()
138+ if path .endswith ( '.html' ):
139+ data = convert_python_html_document ( data .decode ('utf-8' ) )
140+ self .set_header ("Content-Type" , "text/html; charset=utf-8" )
141+ elif path .endswith ('.py' ):
142+ data = python_to_javascript ( data .decode ('utf-8' ), closure_compiler = True )
143+ self .set_header ("Content-Type" , "text/html; charset=utf-8" )
144+
145+ self .set_header ("Content-Length" , len (data ))
146+ self .write ( data )
147+
148+ else :
149+ self .write ('Hello World' )
150+
151+
152+ Handlers = [
153+ (r'/(.*)' , MainHandler )
154+ ]
155+
156+
157+ if __name__ == '__main__' :
158+ assert os .path .isfile ( PATHS ['runtime' ] )
159+ assert os .path .isdir ( PATHS ['pythonscript' ] )
160+ assert os .path .isdir ( PATHS ['bindings' ] )
161+
162+ app = tornado .web .Application (
163+ Handlers ,
164+ #cookie_secret = 'some random text',
165+ #login_url = '/login',
166+ #xsrf_cookies = False,
167+ )
168+
169+
170+ app .listen ( 8080 )
171+ tornado .ioloop .IOLoop .instance ().start ()
0 commit comments