def __init__(self, source_path=None): self.context = Context() self.promise_type = self.context.glob.Promise self.cache = None try: script = Script(source=stdlib.source, filename=stdlib.name) self.context.eval(script) except Exception as e: raise JSBuildError(500, 'Error while compiling stdlib.js') from e if source_path: for file_name in os.listdir(source_path): if not file_name.endswith('.js'): continue logger.info('Compiling file {0}.'.format(os.path.join(source_path, file_name))) try: with open(os.path.join(source_path, file_name), encoding='utf8') as f: script = Script(source=f.read(), filename=file_name) self.context.eval(script) except Exception as e: raise JSBuildError(500, 'Error while compiling.') from e session_api.expose(self.context)
def test_script(): c1 = Context() c1.kappa = 'pride' c2 = Context() s = Script('kappa') assert c1.eval(s) == 'pride' with pytest.raises(JSException): c2.eval(s)
def __init__(self, build_id=None, model=None, source_path=None, autorelease_time=30000, is_server=False): self.build_id = build_id self.model = model self.context = Context() self.promise_type = self.context.glob.Promise self.build_cache = ExpiringDict(2048, 60) # this variable holds amount of users of this build. once this variable hits back to zero, # eventually the build will be released self.refs = 0 self._check_refs = PeriodicCallback(self.__check_build_refs__, autorelease_time) self.released = False try: script = Script(source=stdlib.source, filename=stdlib.name) self.context.eval(script) except Exception as e: logging.exception("Error while compiling stdlib.js") raise JavascriptBuildError(500, str(e)) if source_path: for file_name in os.listdir(source_path): if not file_name.endswith(".js"): continue logging.info("Compiling file {0}".format(os.path.join(source_path, file_name))) try: with open(os.path.join(source_path, file_name), 'r') as f: script = Script(source=f.read(), filename=str(file_name)) self.context.eval(script) except Exception as e: logging.exception("Error while compiling") raise JavascriptBuildError(500, str(e)) expose(self.context, is_server=is_server) if self.build_id: logging.info("Created new build {0}".format(self.build_id)) self._check_refs.start()
def green_func(next_green): def swg(): try: # Kappa next_green.switch() except GreenletExit: # Kappa pass # Kappa c = Context() c.expose(swg) c.eval('swg()')
def test_cross_context_exception_value(context): def call_context(): context.eval('throw {foo: "bar"}') context2 = Context() context2.expose(call_context) try: context2.eval('call_context()') except JSException as e: assert e.value['foo'] == 'bar'
class JSBuild: def __init__(self, source_path=None): self.context = Context() self.promise_type = self.context.glob.Promise self.cache = None try: script = Script(source=stdlib.source, filename=stdlib.name) self.context.eval(script) except Exception as e: raise JSBuildError('Error while compiling stdlib.js') from e if source_path: for file_name in os.listdir(source_path): if not file_name.endswith('.js'): continue logger.info('Compiling file {0}.'.format(os.path.join(source_path, file_name))) try: with open(os.path.join(source_path, file_name), encoding='utf8') as f: script = Script(source=f.read(), filename=file_name) self.context.eval(script) except Exception as e: raise JSBuildError('Error while compiling') from e session_api.expose(self.context) def add_source(self, source_code, filename=None): script = Script(source=source_code, filename=filename) try: self.context.eval(script) except JSException as e: raise JSBuildError('Error while adding source') from e def create_session(self, handler, class_name, args, **env): if class_name not in self.context.glob: raise ClassDoesNotExist clazz = getattr(self.context.glob, class_name) if not getattr(clazz, 'allow_session', False): raise ClassDoesNotExist try: instance = new(clazz, args, env) except (TypeError, JSException) as e: raise JSSessionError('Failed to build session') from e js_session = JSSession(handler, self, instance, self.promise_type, **env) return js_session
def context(): return Context()
def expose(self, context: Context) -> None: context.expose_readonly(**dict(self.items))
def context_with_timeout(): return Context(timeout=0.1)
def context(Global): return Context(Global)
class JavascriptBuild(object): def __init__(self, build_id=None, model=None, source_path=None, autorelease_time=30000, is_server=False): self.build_id = build_id self.model = model self.context = Context() self.promise_type = self.context.glob.Promise self.build_cache = ExpiringDict(2048, 60) # this variable holds amount of users of this build. once this variable hits back to zero, # eventually the build will be released self.refs = 0 self._check_refs = PeriodicCallback(self.__check_build_refs__, autorelease_time) self.released = False try: script = Script(source=stdlib.source, filename=stdlib.name) self.context.eval(script) except Exception as e: logging.exception("Error while compiling stdlib.js") raise JavascriptBuildError(500, str(e)) if source_path: for file_name in os.listdir(source_path): if not file_name.endswith(".js"): continue logging.info("Compiling file {0}".format(os.path.join(source_path, file_name))) try: with open(os.path.join(source_path, file_name), 'r') as f: script = Script(source=f.read(), filename=str(file_name)) self.context.eval(script) except Exception as e: logging.exception("Error while compiling") raise JavascriptBuildError(500, str(e)) expose(self.context, is_server=is_server) if self.build_id: logging.info("Created new build {0}".format(self.build_id)) self._check_refs.start() def __check_build_refs__(self): if self.refs > 0: return if self.build_id: logging.info("Build {0} is being released because no usages left.".format(self.build_id)) self._remove_timeout = None IOLoop.current().add_callback(self.release) @validate(source_code="str", filename="str") def add_source(self, source_code, filename=None): script = Script(source=str(source_code), filename=str(filename)) try: self.context.eval(script) except JSException as e: raise JavascriptBuildError(500, e.message) @validate(class_name="str_name", args="json_dict") def session(self, class_name, args, log=None, debug=None, **env): if class_name not in self.context.glob: raise NoSuchClass() clazz = getattr(self.context.glob, class_name) # each 'session' class should have 'SessionClass.allow_session = true' defined if not getattr(clazz, "allow_session", False): raise NoSuchClass() handler = JavascriptCallHandler(self.build_cache, env, self.context, debug=debug, promise_type=self.promise_type) if log: handler.log = log PromiseContext.current = handler try: instance = new(clazz, args, env) except TypeError: raise JavascriptSessionError(500, "Failed to open session: TypeError while construction") except JSException as e: raise JavascriptSessionError(500, "Failed to open session: " + str(e)) # declare some usage, session will release it using 'session_released' call self.add_ref() return JavascriptSession(self, instance, env, log=log, debug=debug, cache=self.build_cache, promise_type=self.promise_type) @validate(method_name="str_name", args="json_dict") async def call(self, method_name, args, call_timeout=10, **env): if method_name.startswith("_"): raise NoSuchMethod() if method_name in JavascriptSession.CALL_BLACKLIST: raise NoSuchMethod() instance = self.context.glob if not hasattr(instance, method_name): raise NoSuchMethod() method = getattr(instance, method_name) # each plain function should have 'function.allow_call = true' defined if not getattr(method, "allow_call", False): raise NoSuchMethod() handler = JavascriptCallHandler(None, env, self.context, promise_type=self.promise_type) PromiseContext.current = handler # declare some usage until this call is finished self.add_ref() try: try: future = self.context.async_call(method, (args,), JSFuture) except JSException as e: value = e.value if hasattr(value, "code"): if hasattr(value, "stack"): raise JavascriptExecutionError(value.code, value.message, stack=str(value.stack)) else: raise JavascriptExecutionError(value.code, value.message) if hasattr(e, "stack"): raise JavascriptExecutionError(500, str(e), stack=str(e.stack)) raise JavascriptExecutionError(500, str(e)) except APIError as e: raise JavascriptExecutionError(e.code, e.message) except InternalError as e: raise JavascriptExecutionError( e.code, "Internal error: " + e.body) except JavaScriptTerminated: raise JavascriptExecutionError( 408, "Evaluation process timeout: function shouldn't be " "blocking and should rely on async methods instead.") except Exception as e: raise JavascriptExecutionError(500, str(e)) if future.done(): return future.result() try: result = await with_timeout(datetime.timedelta(seconds=call_timeout), future) except TimeoutError: raise APIError(408, "Total function '{0}' call timeout ({1})".format( method_name, call_timeout)) else: return result finally: del handler.context del handler self.remove_ref() def add_ref(self): self.refs += 1 def remove_ref(self): self.refs -= 1 async def session_released(self, session): self.remove_ref() async def release(self): if self.released: return self._check_refs.stop() self._check_refs = None if hasattr(self, "context"): del self.context if self.build_id: logging.info("Build released {0}".format(self.build_id)) if self.model: await self.model.build_released(self) self.released = True