# HG changeset patch # User Atul Varma # Date 1275359377 25200 # Node ID 5d9d2ae0d99589ec515423be6ac61c54c7a8023a # Parent 745b985ee84ae71618af363c7009cc737ef5c8a6 added really basic plugin support diff -r 745b985ee84a -r 5d9d2ae0d995 run_tests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/run_tests.py Mon May 31 19:29:37 2010 -0700 @@ -0,0 +1,5 @@ +if __name__ == '__main__': + import nose + + nose.run(env={'NOSE_WITH_DOCTEST': 1, + 'NOSE_DOCTEST_TESTS': 1}) diff -r 745b985ee84a -r 5d9d2ae0d995 sjsbox/box.py --- a/sjsbox/box.py Mon May 31 18:25:10 2010 -0700 +++ b/sjsbox/box.py Mon May 31 19:29:37 2010 -0700 @@ -3,6 +3,15 @@ import subprocess import multiprocessing as mproc +DEFAULT_PLUGINS = [] + +def get_plugin(name): + parts = name.split('.') + module = __import__(name, fromlist=parts[:-1]) + if not hasattr(module, '__sjsbox_plugin_version__'): + raise ValueError('module %s is not a plugin' % name) + return module + def get_pid_statuses(pids): keywords = ["pid", "%cpu", "%mem", "rss", "utime", "cputime"] cmdline = ["ps"] @@ -34,13 +43,17 @@ #resource.RLIMIT_NOFILE: (10, 20) } - def __init__(self, f, pipe): + def __init__(self, f, pipe, plugins): + self.pipe = pipe + self.globals = {} + for pluginname in plugins: + plugin = get_plugin(pluginname) + plugin.init(self) if f.name.endswith('.js'): import sjsbox.js - self.__impl = sjsbox.js.JsBox(f.contents, f.name) + self.__impl = sjsbox.js.JsBox(self, f.contents, f.name) else: raise ValueError('unknown box type: %s' % f) - self.pipe = pipe def run(self): while True: @@ -61,8 +74,9 @@ class BoxParent(object): TIMEOUT = 3.0 - def __init__(self, sourcefile, logger): + def __init__(self, sourcefile, logger, plugins=DEFAULT_PLUGINS): self.file = sourcefile + self.plugins = plugins self.logger = logger self.child = None self.child_pipe = None @@ -72,7 +86,8 @@ if self.child: self.shutdown() self.child_pipe, pipe = mproc.Pipe() - kwargs = dict(f=self.file, pipe=pipe) + kwargs = dict(f=self.file, pipe=pipe, + plugins=self.plugins) self.child = mproc.Process(target=BoxChild.start, kwargs=kwargs) self.child.start() diff -r 745b985ee84a -r 5d9d2ae0d995 sjsbox/js.py --- a/sjsbox/js.py Mon May 31 18:25:10 2010 -0700 +++ b/sjsbox/js.py Mon May 31 19:29:37 2010 -0700 @@ -11,14 +11,15 @@ from pydertron import jsexposed, JsExposedObject class JsBox(object): - def __init__(self, code, filename): + def __init__(self, box, code, filename): self.sandbox = pydertron.JsSandbox(pydertron.NullFileSystem()) - self.sandbox.set_globals() + self.sandbox.set_globals(**box.globals) self.stderr = StringIO() retval = self.sandbox.run_script(code, filename=filename, stderr=self.stderr) if retval: - print self.stderr.getvalue() + box.logger.error(self.stderr.getvalue()) + raise ValueError('code did not execute successfully') def handle(self, method, path): request = json.dumps(dict(method=method, path=path)) diff -r 745b985ee84a -r 5d9d2ae0d995 tests/test_box.py --- a/tests/test_box.py Mon May 31 18:25:10 2010 -0700 +++ b/tests/test_box.py Mon May 31 19:29:37 2010 -0700 @@ -1,8 +1,28 @@ import unittest +import logging import sjsbox.box from sjsbox.bunch import Bunch +class PluginTests(unittest.TestCase): + def setUp(self): + self.foo = Bunch( + mtime = 0, + name = 'foo.js', + contents = """function handle(request) { + printer("hi " + request.path); return "woot"; }""" + ) + self.box = sjsbox.box.BoxParent(self.foo, + logging.getLogger(), + ['testplugins.printer']) + + def tearDown(self): + self.box.shutdown() + + def test_printer(self): + self.assertEqual(self.box.handle('GET', '/'), + "woot") + class BoxesTests(unittest.TestCase): def setUp(self): self.foo = Bunch( diff -r 745b985ee84a -r 5d9d2ae0d995 tests/testplugins/__init__.py diff -r 745b985ee84a -r 5d9d2ae0d995 tests/testplugins/printer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/testplugins/printer.py Mon May 31 19:29:37 2010 -0700 @@ -0,0 +1,9 @@ +__sjsbox_plugin_version__ = 1 + +def init(box): + def printer(msg): + print msg + + printer.__jsexposed__ = True + + box.globals['printer'] = printer