comparison pydertron.py @ 22:915fdf283ac5

Moved docs out to a separate file.
author Atul Varma <varmaa@toolness.com>
date Thu, 10 Sep 2009 16:59:18 -0700
parents cb73bb169b67
children c2c369402a2e
comparison
equal deleted inserted replaced
21:cb73bb169b67 22:915fdf283ac5
33 # the terms of any one of the MPL, the GPL or the LGPL. 33 # the terms of any one of the MPL, the GPL or the LGPL.
34 # 34 #
35 # ***** END LICENSE BLOCK ***** 35 # ***** END LICENSE BLOCK *****
36 36
37 """ 37 """
38 Pydertron is a high-level wrapper for `Pydermonkey`__ that 38 Pydertron is a high-level wrapper for Pydermonkey that
39 provides convenient, secure object wrapping between JS and Python 39 provides convenient, secure object wrapping between JS and Python
40 space. 40 space.
41
42 The ``JsSandbox`` class encapsulates a JavaScript runtime, context, global
43 object, and a simple `SecurableModule`__ implementation that complies
44 with the `CommonJS`__ standard. It also provides a high-level bridge between
45 Python and JavaScript so that you don't need to deal with any of the
46 low-level details of the Pydermonkey API.
47
48 __ http://code.google.com/p/pydermonkey
49 __ http://wiki.commonjs.org/wiki/CommonJS/Modules/SecurableModules
50 __ http://wiki.commonjs.org/wiki/CommonJS
51
52 For instance, here we'll create a ``JsSandbox`` whose module root
53 points to the ``monkeys`` SecurableModule compliance test over HTTP:
54
55 >>> url = ("http://interoperablejs.googlecode.com/svn/trunk/"
56 ... "compliance/monkeys/")
57 >>> sandbox = JsSandbox(HttpFileSystem(url))
58
59 This compliance test requires a global ``sys`` object that contains one
60 method, ``print()``, that takes two arguments. First, we'll create the
61 ``print()`` function and prepare it for exposure to JS code:
62
63 >>> @jsexposed
64 ... def jsprint(message, label):
65 ... print message, label
66
67 Note the use of the ``@jsexposed`` decorator: all this does is set
68 the function's ``__jsexposed__`` attribute to ``True``. This is
69 done for security purposes: only Python callables satisfying this
70 criteria will be exposed to JavaScript code, to ensure that
71 untrusted JS can't accidentally gain access to privileged Python
72 functionality.
73
74 Creating a JS object can be done like this:
75
76 >>> system = sandbox.new_object()
77
78 We can now access and set properties on this object via either
79 item or attribute lookup, just like in JavaScript. Because
80 ``print`` is a reserved word in Python, though, we'll use item
81 lookup to set the property here:
82
83 >>> system['print'] = jsprint
84
85 Now we tell the sandbox that we want the ``sys`` object to be a
86 global:
87
88 >>> sandbox.set_globals(sys = system)
89
90 And finally, we execute the compliance test by running a one-line
91 script that imports the 'program' module, like so:
92
93 >>> sandbox.run_script("require('program');")
94 PASS monkeys permitted pass
95 DONE info
96 0
97
98 Note the ``0`` in the last line: this is the return value of
99 ``sandbox.run_script()``, which returns ``0`` on success, and
100 ``-1`` if an exception was raised. For instance, the output of bad
101 code looks like this:
102
103 >>> sandbox.run_script("(function foo() { bar(); })();",
104 ... stderr=sys.stdout)
105 Traceback (most recent call last):
106 File "<string>", line 1, in <module>
107 File "<string>", line 1, in foo
108 ReferenceError: bar is not defined
109 -1
110
111 Note that the traceback displayed is actually referring to
112 JavaScript code: one of Pydertron's helpful conveniences is that
113 it makes debugging JS code as much like debugging Python code as
114 possible.
115 """ 41 """
116 42
117 import sys 43 import sys
118 import threading 44 import threading
119 import traceback 45 import traceback