Skip to content

Commit 690b737

Browse files
author
hartsantler
committed
NodeJS: fake Tornado can now serve old index of tests, upgraded to lastest stable NodeJS
added credits, copyright, and license headers to main files. switched to tabs for spacing.
1 parent 3b27796 commit 690b737

9 files changed

Lines changed: 3287 additions & 2939 deletions

File tree

nodejs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# NodeJS Wrapper for PythonJS
33
# by Brett Hartshorn - copyright 2013
44
# License: "New BSD"
5-
# tested with NodeJS v0.6.19
5+
# tested with NodeJS v0.10.22
66

77
import os, sys, subprocess
88

@@ -61,7 +61,7 @@ def get_nodejs_bindings(source):
6161

6262
if len(sys.argv) == 1: ## interactive nodejs console
6363
nodejs = subprocess.Popen(
64-
['nodejs'],
64+
['node'],
6565
stdin = sys.stdin,
6666
stdout = sys.stdout,
6767
)
@@ -72,7 +72,7 @@ def get_nodejs_bindings(source):
7272
if 'NODE_PATH' not in os.environ:
7373
os.environ['NODE_PATH'] = '/usr/local/lib/node_modules/'
7474

75-
cmd = ['nodejs', '/tmp/nodejs-input.js']
75+
cmd = ['node', '/tmp/nodejs-input.js']
7676
if len(sys.argv) > 2:
7777
for arg in sys.argv[2:]:
7878
print 'ARG', arg

nodejs/bindings/os.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
class _fake_path:
66
def __init__(self):
77
self.sep = _path.sep
8+
89
def join(self, a, b):
910
return _path.join( a, b )
1011

@@ -27,6 +28,26 @@ def expanduser(self, path):
2728
## assume that path starts with "~/"
2829
return self.join( process.env.HOME, path[2:] )
2930

31+
def isdir(self, path):
32+
if self.exists( path ):
33+
with javascript:
34+
stat = _fs.statSync( path )
35+
if stat:
36+
return stat.isDirectory()
37+
else:
38+
return False
39+
return False
40+
41+
def isfile(self, path):
42+
if self.exists( path ):
43+
with javascript:
44+
stat = _fs.statSync( path )
45+
if stat:
46+
return stat.isFile()
47+
else:
48+
return False
49+
return False
50+
3051
class _fake_os:
3152
def __init__(self):
3253
self.environ = process.env

nodejs/bindings/tornado.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ def write(self, data):
1616
self._response.write( data )
1717
self._response.end()
1818

19+
def finish(self):
20+
self._response.end()
21+
22+
1923
class _fake_app:
2024
def __init__(self, handlers):
2125
self._handlers = {}
@@ -41,7 +45,7 @@ def on_request(self, request, response):
4145
hclass = self._handlers[ url.pathname ]
4246
handler = hclass( response )
4347
handler.set_header('Transfer-Encoding', 'chunked')
44-
handler.get( url.pathname )
48+
handler.get( url.pathname[1:] ) ## strip root forward slash
4549
else:
4650
response.writeHead(404)
4751
response.end()
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
from nodejs.io import *
2+
from nodejs.os import *
3+
from nodejs.tornado import *
4+
5+
#import os, sys, subprocess, json
6+
7+
PATHS = dict(
8+
webroot = os.path.abspath('tests'),
9+
pythonjs = os.path.abspath('pythonjs'),
10+
bindings = os.path.abspath('bindings'),
11+
runtime = os.path.abspath('pythonjs.js'),
12+
)
13+
14+
15+
16+
def python_to_pythonjs( src, callback ):
17+
path = '/tmp/input1.py'
18+
open( path, 'w' ).write( src )
19+
args = [
20+
os.path.join( PATHS['pythonjs'], 'python_to_pythonjs.py'),
21+
path
22+
]
23+
p = subprocess.call('python2', args, callback=callback )
24+
25+
def pythonjs_to_javascript( src, callback ):
26+
path = '/tmp/input2.py'
27+
open( path, 'w' ).write( src )
28+
args = [
29+
os.path.join( PATHS['pythonjs'], 'pythonjs.py'),
30+
path
31+
]
32+
p = subprocess.call('python2', args, callback=callback )
33+
34+
def python_to_javascript(source, callback):
35+
func = lambda data: pythonjs_to_javascript(data, callback)
36+
python_to_pythonjs( source, func )
37+
38+
39+
40+
#########################################################
41+
def get_main_page():
42+
print 'get_main_page......'
43+
root = PATHS['webroot']
44+
r = ['<html><head><title>index</title></head><body>']
45+
r.append( '<ul>' )
46+
files = os.listdir( root )
47+
files.sort()
48+
for name in files:
49+
path = os.path.join( root, name )
50+
if os.path.isfile( path ):
51+
r.append( '<a href="%s"><li>%s</li></a>' %(name,name) )
52+
r.append('</ul>')
53+
r.append('</body></html>')
54+
return ''.join(r)
55+
56+
57+
def convert_python_html_document( data ):
58+
'''
59+
rewrites html document, converts python scripts into javascript.
60+
example:
61+
<script type="text/python" closure="true">
62+
print("hello world")
63+
</script>
64+
65+
Note:
66+
we need to parse and compile any python binding scripts that appear in the head,
67+
because later scripts may use classes from the bindings, and we need have the
68+
AST introspected data available here to properly inline and for operator overloading.
69+
'''
70+
doc = list()
71+
script = None
72+
use_closure = False
73+
for line in data.splitlines():
74+
if line.strip().startswith('<script'):
75+
if 'src="bindings/' in line:
76+
doc.append( line )
77+
a,b,c = line.split('"')
78+
if b.endswith('.py'): ## make sure the module is cached ##
79+
name = b.split('/')[-1]
80+
path = os.path.join( PATHS['bindings'], name )
81+
src = open(path, 'rb').read().decode('utf-8')
82+
pyjs = python_to_pythonjs( src, module=name.split('.')[0] )
83+
print(pyjs)
84+
print('_'*80)
85+
86+
elif '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+
else:
92+
doc.append( line )
93+
94+
elif line.strip() == '</script>':
95+
if script:
96+
src = '\n'.join( script )
97+
js = python_to_javascript( src, closure_compiler=use_closure, debug=True )
98+
doc.append( js )
99+
doc.append( line )
100+
script = None
101+
102+
elif isinstance( script, list ):
103+
script.append( line )
104+
105+
else:
106+
doc.append( line )
107+
108+
return '\n'.join( doc )
109+
110+
111+
112+
113+
114+
UploadDirectory = '/tmp'
115+
ResourcePaths = []
116+
if os.path.isdir( os.path.expanduser('~/blockly-read-only') ):
117+
ResourcePaths.append( os.path.expanduser('~/blockly-read-only') )
118+
119+
class MainHandler( tornado.web.RequestHandler ):
120+
def get(self, path=None):
121+
print('path', path)
122+
if not path:
123+
self.write( get_main_page() )
124+
elif path == 'pythonscript.js' or path == 'pythonjs.js':
125+
data = open( PATHS['runtime'], 'rb').read()
126+
self.set_header("Content-Type", "text/javascript; charset=utf-8")
127+
self.set_header("Content-Length", len(data))
128+
self.write(data)
129+
elif path.startswith('bindings/'):
130+
name = path.split('/')[-1]
131+
local_path = os.path.join( PATHS['bindings'], name )
132+
133+
if os.path.isfile( local_path ):
134+
data = open(local_path, 'rb').read()
135+
else:
136+
raise tornado.web.HTTPError(404)
137+
138+
if path.endswith('.py'):
139+
print('converting python binding to javascript', name)
140+
module = name.split('.')[0]
141+
data = python_to_javascript( data.decode('utf-8'), closure_compiler=False, module=module )
142+
143+
144+
self.set_header("Content-Type", "text/javascript; charset=utf-8")
145+
self.set_header("Content-Length", len(data))
146+
self.write( data )
147+
148+
elif path.startswith('uploads/'):
149+
name = path.split('/')[-1]
150+
local_path = os.path.join( UploadDirectory, name )
151+
152+
if os.path.isfile( local_path ):
153+
data = open(local_path, 'rb').read()
154+
else:
155+
raise tornado.web.HTTPError(404)
156+
157+
self.set_header("Content-Length", len(data))
158+
self.write( data )
159+
160+
else:
161+
local_path = os.path.join( PATHS['webroot'], path )
162+
if os.path.isfile( local_path ):
163+
data = open(local_path, 'rb').read()
164+
if path.endswith( '.html' ):
165+
data = convert_python_html_document( data.decode('utf-8') )
166+
self.set_header("Content-Type", "text/html; charset=utf-8")
167+
elif path.endswith('.py'):
168+
data = python_to_javascript( data.decode('utf-8'), closure_compiler=True )
169+
self.set_header("Content-Type", "text/html; charset=utf-8")
170+
171+
self.set_header("Content-Length", len(data))
172+
self.write( data )
173+
174+
else:
175+
found = False
176+
for root in ResourcePaths:
177+
local_path = os.path.join( root, path )
178+
if os.path.isfile(local_path):
179+
data = open(local_path, 'rb').read()
180+
self.set_header("Content-Length", len(data))
181+
self.write( data )
182+
found = True
183+
break
184+
185+
if not found:
186+
print( 'FILE NOT FOUND' )
187+
self.finish()
188+
189+
190+
LIBS = dict(
191+
three = {
192+
'three.min.js' : os.path.expanduser( '~/three.js/build/three.min.js'),
193+
'FlyControls.js' : os.path.expanduser( '~/three.js/examples/js/controls/FlyControls.js'),
194+
'OrbitControls.js' : os.path.expanduser( '~/three.js/examples/js/controls/OrbitControls.js'),
195+
'TrackballControls.js' : os.path.expanduser( '~/three.js/examples/js/controls/TrackballControls.js'),
196+
197+
},
198+
tween = {'tween.min.js' : os.path.expanduser( '~/tween.js/build/tween.min.js')},
199+
fonts = {
200+
'gentilis_bold.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/gentilis_bold.typeface.js'),
201+
'gentilis_regular.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/gentilis_regular.typeface.js'),
202+
'optimer_bold.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/optimer_bold.typeface.js'),
203+
'optimer_regular.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/optimer_regular.typeface.js'),
204+
'helvetiker_bold.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/helvetiker_bold.typeface.js'),
205+
'helvetiker_regular.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/helvetiker_regular.typeface.js'),
206+
'droid_sans_regular.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/droid/droid_sans_regular.typeface.js'),
207+
'droid_sans_bold.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/droid/droid_sans_bold.typeface.js'),
208+
'droid_serif_regular.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/droid/droid_serif_regular.typeface.js'),
209+
'droid_serif_bold.typeface.js' : os.path.expanduser( '~/three.js/examples/fonts/droid/droid_serif_bold.typeface.js'),
210+
},
211+
ace = {
212+
'ace.js': os.path.expanduser( '~/ace-builds/src-noconflict/ace.js'),
213+
'theme-monokai.js':os.path.expanduser( '~/ace-builds/src-noconflict/theme-monokai.js'),
214+
'mode-python.js':os.path.expanduser( '~/ace-builds/src-noconflict/mode-python.js'),
215+
'mode-javascript.js':os.path.expanduser( '~/ace-builds/src-noconflict/mode-javascript.js'),
216+
'worker-javascript.js':os.path.expanduser( '~/ace-builds/src-noconflict/worker-javascript.js'),
217+
},
218+
physijs = {
219+
'physi.js' : os.path.expanduser( '~/Physijs/physi.js'),
220+
'physijs_worker.js' : os.path.expanduser( '~/Physijs/physijs_worker.js'),
221+
},
222+
ammo = {
223+
'ammo.js' : os.path.expanduser( '~/Physijs/examples/js/ammo.js'),
224+
},
225+
pixi = {
226+
'pixi.js' : os.path.expanduser( '~/pixi.js/bin/pixi.js'),
227+
}
228+
229+
)
230+
231+
class LibsHandler( tornado.web.RequestHandler ):
232+
def get(self, path=None):
233+
print('path', path)
234+
module, name = path.split('/')
235+
assert module in LIBS
236+
assert name in LIBS[ module ]
237+
if os.path.isfile( LIBS[module][name] ):
238+
data = open( LIBS[module][name], 'rb').read()
239+
else:
240+
raise tornado.web.HTTPError(404)
241+
242+
self.set_header("Content-Type", "text/javascript; charset=utf-8")
243+
self.set_header("Content-Length", len(data))
244+
self.write( data )
245+
246+
247+
class WebSocketHandler(tornado.websocket.WebSocketHandler):
248+
def open(self):
249+
print( self.request.connection )
250+
251+
def on_message(self, msg, flags=None):
252+
if hasattr(self.ws_connection, 'previous_command') and self.ws_connection.previous_command and self.ws_connection.previous_command.get('binary', False):
253+
if self.ws_connection.previous_command['command'] == 'upload':
254+
path = os.path.join(
255+
UploadDirectory,
256+
self.ws_connection.previous_command['file_name']
257+
)
258+
f = open( path, 'wb' )
259+
f.write( msg )
260+
f.close()
261+
262+
self.ws_connection.previous_command = None
263+
264+
else:
265+
print('on json message', msg)
266+
267+
ob = json.loads( msg )
268+
if isinstance(ob, dict):
269+
if 'command' in ob:
270+
if ob['command'] == 'compile':
271+
js = python_to_javascript( ob['code'] )
272+
self.write_message( {'eval':js})
273+
elif ob['command'] == 'upload':
274+
print('ready for upload...')
275+
print( ob['file_name'] )
276+
277+
self.ws_connection.previous_command = ob
278+
279+
else:
280+
self.write_message('"hello client"')
281+
282+
def on_close(self):
283+
print('websocket closed')
284+
if self.ws_connection:
285+
self.close()
286+
287+
288+
Handlers = [
289+
('/websocket', WebSocketHandler),
290+
('/libs/', LibsHandler),
291+
('/', MainHandler)
292+
]
293+
294+
295+
296+
app = tornado.web.Application( Handlers )
297+
app.listen( 8080 )

0 commit comments

Comments
 (0)