From 4453408d045f69ab76ae4cfc7787737b71294eca Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 16 Oct 2018 18:36:11 +0100 Subject: [PATCH] Allow loading cached compiled models using hook (#8336) * Initial implementation of loading compiled CustomModel implementation from file * Added utility to save compiled models * Provide hook to look up cached implementation * Add public API to get and set custom model cache * Reorganized functions * Pass the CustomModel to the caching hook --- bokeh/util/compiler.py | 66 ++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/bokeh/util/compiler.py b/bokeh/util/compiler.py index ed13b9a9e4e..ef93d1cdf56 100644 --- a/bokeh/util/compiler.py +++ b/bokeh/util/compiler.py @@ -248,7 +248,7 @@ class TypeScript(Inline): .. code-block:: python class MyExt(Model): - __implementation__ = TypeScript(""" """) + __implementation__ = TypeScript(""" """) ''' @property @@ -256,14 +256,14 @@ def lang(self): return "typescript" class JavaScript(Inline): - ''' An implementation for a Bokeh custom model in JavaSript + ''' An implementation for a Bokeh custom model in JavaScript Example: .. code-block:: python class MyExt(Model): - __implementation__ = Javacript(""" """) + __implementation__ = Javacript(""" """) ''' @property @@ -364,10 +364,26 @@ def dependencies(self): def module(self): return "custom/%s" % snakify(self.full_name) -def bundle_models(models): - """Create a bundle of `models`. """ - custom_models = {} +def _model_cache_no_op(model, implementation): + """Return cached compiled implementation""" + return None + +_CACHING_IMPLEMENTATION = _model_cache_no_op + +def get_cache_hook(): + '''Returns the current cache hook used to look up the compiled + code given the CustomModel and Implementation''' + return _CACHING_IMPLEMENTATION +def set_cache_hook(hook): + '''Sets a compiled model cache hook used to look up the compiled + code given the CustomModel and Implementation''' + global _CACHING_IMPLEMENTATION + _CACHING_IMPLEMENTATION = hook + +def _get_custom_models(models): + """Returns CustomModels for models with a custom `__implementation__`""" + custom_models = {} for cls in models: impl = getattr(cls, "__implementation__", None) @@ -377,19 +393,11 @@ def bundle_models(models): if not custom_models: return None + return custom_models +def _compile_models(custom_models): + """Returns the compiled implementation of supplied `models`. """ ordered_models = sorted(custom_models.values(), key=lambda model: model.full_name) - - exports = [] - modules = [] - - def read_json(name): - with io.open(join(bokehjs_dir, "js", name + ".json"), encoding="utf-8") as f: - return json.loads(f.read()) - - - bundles = ["bokeh", "bokeh-api", "bokeh-widgets", "bokeh-tables", "bokeh-gl"] - known_modules = set(sum([ read_json(name) for name in bundles ], [])) custom_impls = {} dependencies = [] @@ -402,13 +410,35 @@ def read_json(name): for model in ordered_models: impl = model.implementation - compiled = nodejs_compile(impl.code, lang=impl.lang, file=impl.file) + compiled = _CACHING_IMPLEMENTATION(model, impl) + if compiled is None: + compiled = nodejs_compile(impl.code, lang=impl.lang, file=impl.file) if "error" in compiled: raise CompilationError(compiled.error) custom_impls[model.full_name] = compiled + return custom_impls + +def bundle_models(models): + """Create a bundle of `models`. """ + + custom_models = _get_custom_models(models) + if custom_models is None: + return + + exports = [] + modules = [] + + def read_json(name): + with io.open(join(bokehjs_dir, "js", name + ".json"), encoding="utf-8") as f: + return json.loads(f.read()) + + bundles = ["bokeh", "bokeh-api", "bokeh-widgets", "bokeh-tables", "bokeh-gl"] + known_modules = set(sum([ read_json(name) for name in bundles ], [])) + custom_impls = _compile_models(custom_models) + extra_modules = {} def resolve_modules(to_resolve, root):