Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update panel to use bokeh build #626

Merged
merged 19 commits into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ jobs:
- source activate test-environment
- conda install -c conda-forge mesalib
- doit develop_install -o recommended -o tests -o build $CHANS_DEV
- python setup.py develop --no-deps
- bokeh sampledata
- doit env_capture
before_script:
Expand Down
31 changes: 31 additions & 0 deletions dodo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
os.environ["PYCTDEV_ECOSYSTEM"] = "conda"

from pyctdev import * # noqa: api
from pyctdev import CmdAction
from pyctdev._conda import _options_param, _channel_param, _conda_build_deps, _conda_install_with_options_hacked

def task_pip_on_conda():
"""Experimental: provide pip build env via conda"""
Expand All @@ -14,3 +16,32 @@ def task_pip_on_conda():
# this interferes with pip-installed nose
'conda remove -y --force nose'
]}


def _build_dev(channel):
channels = " ".join(['-c %s' % c for c in channel])
return "conda build %s conda.recipe/ --build-only" % channels


def task_develop_install():
"""python develop install, with specified optional groups of dependencies (installed by conda only).

Typically ``conda install "test dependencies" && pip install -e . --no-deps``.

Pass --options multiple times to specify other optional groups
(see project's setup.py for available options).

E.g.

``doit develop_install -o examples -o tests``
``doit develop_install -o all``

"""
return {'actions': [
CmdAction(_conda_build_deps),
CmdAction(_conda_install_with_options_hacked),
#CmdAction(_build_dev), # Switch to locally built version at later point
#"conda install --use-local panel"
"conda uninstall panel --force",
"python setup.py develop --no-deps"],
'params': [_options_param,_channel_param]}
3 changes: 3 additions & 0 deletions panel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules/
/dist/
/.bokeh
10 changes: 5 additions & 5 deletions panel/_templates/autoload_panel_js.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,16 @@ calls it with the rendered model.
document.body.appendChild(element);
}

var js_urls = {{ js_urls|json }};
var css_urls = {{ css_urls|json }};
var js_urls = {{ bundle.js_urls|json }};
var css_urls = {{ bundle.css_urls|json }};

var inline_js = [
{%- for css in css_raw %}
{%- for css in bundle.css_raw %}
function(Bokeh) {
inject_raw_css({{ css }});
inject_raw_css({{ css|json }});
},
{%- endfor %}
{%- for js in js_raw %}
{%- for js in bundle.js_raw %}
function(Bokeh) {
{{ js|indent(6) }}
},
Expand Down
1 change: 1 addition & 0 deletions panel/bokeh.ext.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
73 changes: 6 additions & 67 deletions panel/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,10 @@
"""
from __future__ import absolute_import, division, unicode_literals

import hashlib
import io
import json
import os

from bokeh.util.compiler import (AttrDict, get_cache_hook, set_cache_hook,
_get_custom_models, _compile_models)

#---------------------------------------------------------------------
# Public API
#---------------------------------------------------------------------

# Global variables
CUSTOM_MODELS = {}


def load_compiled_models(custom_model, implementation):
"""
Custom hook to load cached implementation of custom models.
"""
compiled = old_hook(custom_model, implementation)
if compiled is not None:
return compiled

model = CUSTOM_MODELS.get(custom_model.full_name)
if model is None:
return
ts_file = model.__implementation__
json_file = ts_file.replace('.ts', '.json')
if not os.path.isfile(json_file):
return
with io.open(ts_file, encoding="utf-8") as f:
code = f.read()
with io.open(json_file, encoding="utf-8") as f:
compiled = json.load(f)
hashed = hashlib.sha256(code.encode('utf-8')).hexdigest()
if compiled['hash'] == hashed:
return AttrDict(compiled)
return None


def build_custom_models():
"""
Compiles custom bokeh models and stores the compiled JSON alongside
the original code.
"""
from .config import panel_extension
# Ensure that all optional models are loaded
for imp in panel_extension._imports.values():
__import__(imp)

custom_models = _get_custom_models(list(CUSTOM_MODELS.values()))
compiled_models = _compile_models(custom_models)
for name, model in custom_models.items():
compiled = compiled_models.get(name)
if compiled is None:
return
print('\tBuilt %s custom model' % name)
impl = model.implementation
hashed = hashlib.sha256(impl.code.encode('utf-8')).hexdigest()
compiled['hash'] = hashed
fp = impl.file.replace('.ts', '.json')
with open(fp, 'w') as f:
json.dump(compiled, f)


def require_components():
"""
Returns JS snippet to load the required dependencies in the classic
Expand All @@ -77,7 +15,12 @@ def require_components():
from .config import config

configs, requirements, exports = [], [], []
js_requires = list(CUSTOM_MODELS.values())
js_requires = []

from bokeh.model import Model
for qual_name, model in Model.model_class_reverse_map.items():
if qual_name.split(".")[0] == "panel":
js_requires.append(model)

for export, js in config.js_files.items():
name = js.split('/')[-1].replace('.min', '').split('.')[-2]
Expand All @@ -104,7 +47,3 @@ def require_components():
requirements.append(e)
exports.append(value)
return configs, requirements, exports


old_hook = get_cache_hook()
set_cache_hook(load_compiled_models)
5 changes: 5 additions & 0 deletions panel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as Panel from "./models"
export {Panel}

import {register_models} from "@bokehjs/base"
register_models(Panel as any)
18 changes: 7 additions & 11 deletions panel/io/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
from bokeh.core.json_encoder import serialize_json
from bokeh.document import Document
from bokeh.embed import server_document
from bokeh.embed.bundle import bundle_for_objs_and_resources
from bokeh.embed.elements import div_for_render_item
from bokeh.embed.util import standalone_docs_json_and_render_items
from bokeh.models import CustomJS, LayoutDOM, Model
from bokeh.resources import CDN, INLINE
from bokeh.util.compiler import bundle_all_models
from bokeh.util.string import encode_utf8
from jinja2 import Environment, Markup, FileSystemLoader
from pyviz_comms import (
Expand Down Expand Up @@ -111,12 +111,9 @@ def get_env():
AUTOLOAD_NB_JS = _env.get_template("autoload_panel_js.js")


def _autoload_js(resources, custom_models_js, configs, requirements, exports, load_timeout=5000):
def _autoload_js(bundle, configs, requirements, exports, load_timeout=5000):
return AUTOLOAD_NB_JS.render(
js_urls = resources.js_files,
css_urls = resources.css_files,
js_raw = resources.js_raw + [custom_models_js],
css_raw = resources.css_raw_str,
bundle = bundle,
force = True,
timeout = load_timeout,
configs = configs,
Expand Down Expand Up @@ -199,14 +196,13 @@ def load_notebook(inline=True, load_timeout=5000):
from IPython.display import publish_display_data

resources = INLINE if inline else CDN
custom_models_js = bundle_all_models() or ""

bundle = bundle_for_objs_and_resources(None, resources)
configs, requirements, exports = require_components()
bokeh_js = _autoload_js(resources, custom_models_js, configs,
requirements, exports, load_timeout)

bokeh_js = _autoload_js(bundle, configs, requirements, exports, load_timeout)
publish_display_data({
'application/javascript': bokeh_js,
LOAD_MIME : bokeh_js
LOAD_MIME: bokeh_js,
})
bokeh.io.notebook.curstate().output_notebook()

Expand Down
10 changes: 0 additions & 10 deletions panel/models/ace.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
"""
Defines custom AcePlot bokeh model to render Ace editor.
"""
import os

from bokeh.core.properties import String, Override, Dict, Any, List, Bool
from bokeh.models import HTMLBox

from ..compiler import CUSTOM_MODELS

class AcePlot(HTMLBox):
"""
A Bokeh model that wraps around a Ace editor and renders it inside
Expand All @@ -21,8 +17,6 @@ class AcePlot(HTMLBox):
'ace_lang_tools': 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.3/ext-language_tools'},
'exports': {'ace': 'ace'}}

__implementation__ = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'ace.ts')

code = String()

theme = String(default='chrome')
Expand All @@ -36,7 +30,3 @@ class AcePlot(HTMLBox):
height = Override(default=300)

width = Override(default=300)



CUSTOM_MODELS['panel.models.ace.AcePlot'] = AcePlot
14 changes: 7 additions & 7 deletions panel/models/ace.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as p from "core/properties"
import {HTMLBox, HTMLBoxView} from "models/layouts/html_box"
import { div } from 'core/dom';
import * as p from "@bokehjs/core/properties"
import {HTMLBox, HTMLBoxView} from "@bokehjs/models/layouts/html_box"
import { div } from "@bokehjs/core/dom";

function ID() {
// Math.random should be unique because of its seeding algorithm.
Expand Down Expand Up @@ -85,7 +85,7 @@ export class AcePlotView extends HTMLBoxView {
super.after_layout()
this._editor.resize()
}

}

export namespace AcePlot {
Expand All @@ -108,8 +108,9 @@ export class AcePlot extends HTMLBox {
super(attrs)
}

static initClass(): void {
this.prototype.type = "AcePlot"
static __module__ = "panel.models.ace"

static init_AcePlot(): void {
this.prototype.default_view = AcePlotView

this.define<AcePlot.Props>({
Expand All @@ -126,4 +127,3 @@ export class AcePlot extends HTMLBox {
})
}
}
AcePlot.initClass()
13 changes: 6 additions & 7 deletions panel/models/audio.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as p from "core/properties"
import {Widget, WidgetView} from "models/widgets/widget"
import * as p from "@bokehjs/core/properties"
import {Widget, WidgetView} from "@bokehjs/models/widgets/widget"

export class AudioView extends WidgetView {
model: Audio
Expand Down Expand Up @@ -112,19 +112,18 @@ export abstract class Audio extends Widget {
super(attrs)
}

static initClass(): void {
this.prototype.type = "Audio"
static __module__ = "panel.models.widgets"

static init_Audio(): void {
this.prototype.default_view = AudioView

this.define<Audio.Props>({
loop: [ p.Boolean, false ],
paused: [ p.Boolean, true ],
time: [ p.Number, 0 ],
throttle: [ p.Number, 250 ],
throttle: [ p.Number, 250 ],
value: [ p.Any, '' ],
volume: [ p.Number, null ],
})
}
}

Audio.initClass()
10 changes: 5 additions & 5 deletions panel/models/html.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as p from "core/properties"
import {Markup, MarkupView} from "models/widgets/markup"
import * as p from "@bokehjs/core/properties"
import {Markup, MarkupView} from "@bokehjs/models/widgets/markup"

function htmlDecode(input: string): string | null {
var doc = new DOMParser().parseFromString(input, "text/html");
Expand Down Expand Up @@ -43,9 +43,9 @@ export class HTML extends Markup {
super(attrs)
}

static initClass(): void {
this.prototype.type = "HTML"
static __module__ = "panel.models.markup"

static init_HTML(): void {
this.prototype.default_view = HTMLView
}
}
HTML.initClass()
11 changes: 11 additions & 0 deletions panel/models/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export {AcePlot} from "./ace"
export {Audio} from "./audio"
export {HTML} from "./html"
export {KaTeX} from "./katex"
export {MathJax} from "./mathjax"
export {Player} from "./player"
export {PlotlyPlot} from "./plotly"
export {State} from "./state"
export {VegaPlot} from "./vega"
export {VideoStream} from "./videostream"
export {VTKPlot} from "./vtk"
9 changes: 0 additions & 9 deletions panel/models/katex.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
"""
Defines a custom KaTeX bokeh model to render text using KaTeX.
"""
import os

from bokeh.models import Markup

from ..compiler import CUSTOM_MODELS


class KaTeX(Markup):
"""
Expand All @@ -21,8 +17,3 @@ class KaTeX(Markup):
'exports': {'katex': 'katex', 'autoLoad': 'renderMathInElement'}}

__css__ = ["https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css"]

__implementation__ = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'katex.ts')


CUSTOM_MODELS['panel.models.katex.KaTeX'] = KaTeX
Loading