Skip to content

Commit 7076eac

Browse files
author
hartsantler
committed
added test for Three.js, and hackish way to import star from an external module.
1 parent bdbd0fb commit 7076eac

4 files changed

Lines changed: 103 additions & 28 deletions

File tree

bindings/three.py

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,41 @@
22
# by Brett Hartshorn - copyright 2013
33
# License: PSFLv2 - http://www.python.org/psf/license/
44

5+
class Vector3:
6+
def __init__(self, x=0, y=0, z=0 ):
7+
self._vec = JS('new THREE.Vector3(x,y,z)')
8+
9+
def set(self, x,y,z):
10+
vec = self._vec
11+
JS('vec.set(x,y,z)')
12+
13+
@property
14+
def x(self):
15+
vec = self._vec
16+
return JS('vec.x')
17+
@x.setter
18+
def x(self, value):
19+
vec = self._vec
20+
JS('vec.x=value')
21+
22+
@property
23+
def y(self):
24+
vec = self._vec
25+
return JS('vec.y')
26+
@y.setter
27+
def y(self, value):
28+
vec = self._vec
29+
JS('vec.y=value')
30+
31+
@property
32+
def z(self):
33+
vec = self._vec
34+
return JS('vec.z')
35+
@x.setter
36+
def z(self, value):
37+
vec = self._vec
38+
JS('vec.z=value')
539

6-
class _Vector3:
7-
def __init__(self, jsobject=None):
8-
self._vec = jsobject
940

1041
class _ObjectBase:
1142
def add(self, child):
@@ -27,10 +58,10 @@ def __init__(self, fov, aspect, near, far):
2758
self._object = JS('new THREE.PerspectiveCamera(fov, aspect, near, far)')
2859

2960
def setLens(self, focalLength, frameSize):
30-
'''Uses Focal Length (in mm) to estimate and set FOV
61+
"""Uses Focal Length (in mm) to estimate and set FOV
3162
* 35mm (fullframe) camera is used if frame size is not specified;
3263
* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
33-
'''
64+
"""
3465
ob = self._object
3566
JS('ob.setLens(focalLength, frameSize)')
3667

@@ -87,6 +118,7 @@ def loadTextureCube( urls ):
87118
class _Three:
88119
def __init__(self):
89120
self.ImageUtils = _ImageUtils()
121+
self.Vector3 = Vector3
90122

91123
def Scene(self):
92124
return _Scene()

pythonscript/python_to_pythonjs.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python
2-
import sys
2+
import os, sys, pickle
33
from types import GeneratorType
44

55
from ast import Str
@@ -67,7 +67,7 @@ class PythonToPythonJS(NodeVisitor):
6767

6868
identifier = 0
6969

70-
def __init__(self):
70+
def __init__(self, module=None, module_path=None):
7171
super(PythonToPythonJS, self).__init__()
7272
self._classes = dict() ## class name : [method names]
7373
self._inline_classes = dict() ## class name : [attribute names]
@@ -77,6 +77,32 @@ def __init__(self):
7777
self._decorator_properties = dict()
7878
self._decorator_class_props = dict()
7979

80+
self._module = module
81+
self._module_path = module_path
82+
assert os.path.isdir( module_path )
83+
84+
def save_module(self):
85+
if self._module and self._module_path:
86+
a = dict(
87+
classes = self._classes,
88+
inline_classes = self._inline_classes,
89+
decorator_class_props = self._decorator_class_props,
90+
)
91+
pickle.dump( a, open(os.path.join(self._module_path, self._module+'.module'), 'wb') )
92+
93+
def visit_ImportFrom(self, node):
94+
if node.module in MINI_STDLIB:
95+
for n in node.names:
96+
if n.name in MINI_STDLIB[ node.module ]:
97+
writer.write( 'JS("%s")' %MINI_STDLIB[node.module][n.name] )
98+
99+
elif self._module_path and node.module+'.module' in os.listdir(self._module_path):
100+
f = open( os.path.join(self._module_path, node.module+'.module'), 'rb' )
101+
a = pickle.load( f ); f.close()
102+
self._classes.update( a['classes'] )
103+
self._inline_classes.update( a['inline_classes'] )
104+
self._decorator_class_props.update( a['decorator_class_props'] )
105+
80106
def visit_Assert(self, node):
81107
## hijacking "assert isinstance(a,A)" as a type system ##
82108
if isinstance( node.test, Call ) and node.test.func.id == 'isinstance':
@@ -98,12 +124,6 @@ def visit_AugAssign(self, node):
98124
a = '%s %s= %s' %(self.visit(node.target), self.visit(node.op), self.visit(node.value))
99125
writer.write(a)
100126

101-
def visit_ImportFrom(self, node):
102-
if node.module in MINI_STDLIB:
103-
for n in node.names:
104-
if n.name in MINI_STDLIB[ node.module ]:
105-
writer.write( 'JS("%s")' %MINI_STDLIB[node.module][n.name] )
106-
107127
def visit_Yield(self, node):
108128
return 'yield %s' % self.visit(node.value)
109129

@@ -565,7 +585,22 @@ def main(script):
565585

566586

567587
def command():
568-
print( main(sys.stdin.read()) )
588+
module = module_path = None
589+
590+
data = sys.stdin.read()
591+
if data.startswith('#!'):
592+
header = data[ 2 : data.index('\n') ]
593+
data = data[ data.index('\n')+1 : ]
594+
if ';' in header:
595+
module_path, module = header.split(';')
596+
else:
597+
module_path = header
598+
599+
compiler = PythonToPythonJS( module=module, module_path=module_path )
600+
compiler.visit( parse(data) )
601+
compiler.save_module()
602+
output = writer.getvalue()
603+
print( output ) ## pipe to stdout
569604

570605

571606
if __name__ == '__main__':

tests/server.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@
2525

2626

2727

28-
def python_to_pythonjs( src ):
28+
def python_to_pythonjs( src, module=None ):
29+
cmdheader = '#!/tmp' ## module_path
30+
if module:
31+
assert '.' not in module
32+
cmdheader += ';' + module
33+
cmdheader += '\n'
34+
print('cmd-header', cmdheader)
35+
2936
p = subprocess.Popen(
3037
['python2', os.path.join( PATHS['pythonscript'], 'python_to_pythonjs.py')],
3138
stdin = subprocess.PIPE,
3239
stdout = subprocess.PIPE
3340
)
34-
stdout, stderr = p.communicate( src.encode('utf-8') )
41+
stdout, stderr = p.communicate( (cmdheader + src).encode('utf-8') )
3542
return stdout.decode('utf-8')
3643

3744
def pythonjs_to_javascript( src, closure_compiler=False ):
@@ -57,8 +64,9 @@ def pythonjs_to_javascript( src, closure_compiler=False ):
5764

5865
return a
5966

60-
def python_to_javascript( src, closure_compiler=False ):
61-
a = python_to_pythonjs( src ); print(a)
67+
def python_to_javascript( src, module=None, closure_compiler=False, debug=False ):
68+
a = python_to_pythonjs( src, module=module )
69+
if debug: print( a )
6270
return pythonjs_to_javascript( a, closure_compiler=closure_compiler )
6371

6472

@@ -99,7 +107,7 @@ def convert_python_html_document( data ):
99107
elif line.strip() == '</script>':
100108
if script:
101109
src = '\n'.join( script )
102-
js = python_to_javascript( src, closure_compiler=use_closure )
110+
js = python_to_javascript( src, closure_compiler=use_closure, debug=True )
103111
doc.append( js )
104112
doc.append( line )
105113
script = None
@@ -132,7 +140,9 @@ def get(self, path=None):
132140
raise tornado.web.HTTPError(404)
133141

134142
if path.endswith('.py'):
135-
data = python_to_javascript( data.decode('utf-8'), closure_compiler=False )
143+
print('converting python binding to javascript', name)
144+
module = name.split('.')[0]
145+
data = python_to_javascript( data.decode('utf-8'), closure_compiler=False, module=module )
136146

137147
self.set_header("Content-Type", "text/javascript; charset=utf-8")
138148
self.set_header("Content-Length", len(data))

tests/test_threejs.html

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
<html>
22
<head>
3+
<script src="pythonscript.js"></script>
34
<script src="libs/three/three.min.js"></script>
45
<script src="bindings/three.py"></script>
5-
<script src="pythonscript.js"></script>
66

77
<script type="text/python" closure="true">
8-
def inline_me():
9-
return 1
8+
from three import *
109

1110
def test():
12-
i = 0
13-
while i < 10:
14-
i += inline_me()
15-
16-
print 'hello world', i
11+
v = Vector3(1, 2, 3)
12+
print( v.x )
13+
print( v.y )
14+
print( v.z )
1715

1816
</script>
1917
</head>

0 commit comments

Comments
 (0)