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

Support for Bokeh 3.4 #6072

Merged
merged 32 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
70147af
Update Bokeh pins
hoxbro Dec 18, 2023
1170857
Update to work with resource.url
hoxbro Dec 18, 2023
23cbde8
comment out CustomSelect for now
hoxbro Dec 18, 2023
522e5f8
Update test channel
hoxbro Dec 18, 2023
83a948c
UI test label dev too
hoxbro Dec 18, 2023
171f100
Fix easy failing tests
hoxbro Dec 18, 2023
1c44472
Merge branch 'main' into bokeh34
hoxbro Jan 24, 2024
990f27b
Clean up string
hoxbro Jan 24, 2024
b360a90
Update bokeh pin
hoxbro Jan 24, 2024
90b6eb5
Update package.json
hoxbro Jan 24, 2024
3ff2f1d
Update to work with Bokeh 3.4.0
hoxbro Jan 24, 2024
1299bba
Use URL for bundles to fix autoload.js
hoxbro Jan 24, 2024
f454c93
Use pytest.mark.asyncio for test
hoxbro Jan 24, 2024
23d60c7
Handle URL in notebooks
hoxbro Jan 24, 2024
c4d2dac
Hack around Bokeh setting this.input_el.id
hoxbro Jan 24, 2024
718f4fa
Convert URL to str if needed
hoxbro Jan 24, 2024
deada7d
Comment out pytest.mark.asyncio line
hoxbro Jan 24, 2024
e9d3b81
Use custom encoder to handle URL
hoxbro Jan 24, 2024
5df388b
Remove pytest.mark.asyncio from tests
hoxbro Jan 24, 2024
7f0247d
Update panel/io/resources.py
hoxbro Jan 24, 2024
faddd2e
Use PaletteSelect
hoxbro Jan 24, 2024
f7440ed
Fix indentation in file_download.ts
hoxbro Jan 25, 2024
bc386fe
Update setup.py
hoxbro Jan 25, 2024
a717d9c
Update setup.py
hoxbro Jan 25, 2024
f4455b3
Try pin playwright
hoxbro Jan 25, 2024
b92ae61
Remove playwright pin again
hoxbro Jan 29, 2024
9ba3d7a
Temporarily disable reruns in UI
hoxbro Jan 29, 2024
9980b02
Upgrade to bokeh 3.4.0-dev.8
mattpap Feb 15, 2024
816ed20
Fix tsconfig.json
mattpap Feb 12, 2024
c1056b5
Rename rebuild() -> update_children()
mattpap Feb 15, 2024
6bd6a3c
Re-activate reruns for UI tests
hoxbro Feb 15, 2024
d0a03b1
Fix tests
philippjfr Feb 16, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ jobs:
with:
name: unit_test_suite
python-version: ${{ matrix.python-version }}
channels: pyviz/label/dev,numba,bokeh,conda-forge,nodefaults
channels: pyviz/label/dev,numba,bokeh/label/dev,conda-forge,nodefaults
conda-update: true
nodejs: true
envs: -o examples -o recommended -o tests -o build
Expand Down Expand Up @@ -222,7 +222,7 @@ jobs:
with:
name: ui_test_suite
python-version: 3.9
channels: pyviz/label/dev,bokeh,conda-forge,nodefaults
channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults
envs: "-o recommended -o tests -o build"
cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }}
nodejs: true
Expand Down
25 changes: 22 additions & 3 deletions panel/io/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from markupsafe import Markup

from ..config import config, panel_extension as extension
from ..util import isurl, url_path
from ..util import bokeh34, isurl, url_path
from .state import state

if TYPE_CHECKING:
Expand Down Expand Up @@ -69,10 +69,18 @@ def get_env():
def conffilter(value):
return json.dumps(OrderedDict(value)).replace('"', '\'')

class json_dumps(json.JSONEncoder):
def default(self, obj):
if bokeh34:
from bokeh.embed.bundle import URL
if isinstance(obj, URL):
return str(obj)
return super().default(obj)

_env = get_env()
_env.trim_blocks = True
_env.lstrip_blocks = True
_env.filters['json'] = lambda obj: Markup(json.dumps(obj))
_env.filters['json'] = lambda obj: Markup(json.dumps(obj, cls=json_dumps))
_env.filters['conffilter'] = conffilter
_env.filters['sorted'] = sorted

Expand Down Expand Up @@ -383,7 +391,7 @@ def bundle_resources(roots, resources, notebook=False, reloading=False, enable_m
extensions = _bundle_extensions(None, js_resources)
if reloading:
extensions = [
ext for ext in extensions if not (ext.cdn_url is not None and ext.cdn_url.startswith('https://unpkg.com/@holoviz/panel@'))
ext for ext in extensions if not (ext.cdn_url is not None and str(ext.cdn_url).startswith('https://unpkg.com/@holoviz/panel@'))
]

extra_js = []
Expand All @@ -392,6 +400,8 @@ def bundle_resources(roots, resources, notebook=False, reloading=False, enable_m
elif mode == "server":
for bundle in extensions:
server_url = bundle.server_url
if not isinstance(server_url, str):
server_url = str(server_url)
if resources.root_url and not resources.absolute:
server_url = server_url.replace(resources.root_url, '', 1)
if state.rel_path:
Expand All @@ -412,6 +422,13 @@ def bundle_resources(roots, resources, notebook=False, reloading=False, enable_m
js_raw.append(ext)

hashes = js_resources.hashes if js_resources else {}

if bokeh34:
from bokeh.embed.bundle import URL

js_files = list(map(URL, js_files))
css_files = list(map(URL, css_files))

return Bundle(
css_files=css_files,
css_raw=css_raw,
Expand Down Expand Up @@ -599,6 +616,8 @@ def adjust_paths(self, resources):
new_resources = []
cdn_base = f'{config.npm_cdn}/@holoviz/panel@{JS_VERSION}/dist/'
for resource in resources:
if not isinstance(resource, str):
resource = str(resource)
resource = resource.replace('https://unpkg.com', config.npm_cdn)
if resource.startswith(cdn_base):
resource = resource.replace(cdn_base, CDN_DIST)
Expand Down
2 changes: 1 addition & 1 deletion panel/models/customselect.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Select, SelectView } from "@bokehjs/models/widgets/selectbox"
import { Select, SelectView } from "@bokehjs/models/widgets/select"
import * as p from "@bokehjs/core/properties"


Expand Down
7 changes: 4 additions & 3 deletions panel/models/datetime_picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ export class DatetimePickerView extends InputWidgetView {
return [...super.stylesheets(), flatpickr_css]
}

_render_input(): HTMLElement {
return this.input_el = input({type: "text", class: inputs.input, disabled: this.model.disabled})
}

render(): void {
if (this._picker != null)
return

super.render()

this.input_el = input({type: "text", class: inputs.input, disabled: this.model.disabled})
this.group_el.appendChild(this.input_el)

const options: flatpickr.Options.Options = {
appendTo: this.group_el,
positionElement: this.input_el,
Expand Down
17 changes: 11 additions & 6 deletions panel/models/file_download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Icon, IconView} from "@bokehjs/models/ui/icons/icon"

import buttons_css, * as buttons from "@bokehjs/styles/buttons.css"
import type {StyleSheetLike} from "@bokehjs/core/dom"
import {prepend, nbsp, text, button} from "@bokehjs/core/dom"
import {prepend, nbsp, text, button, input} from "@bokehjs/core/dom"

function dataURItoBlob(dataURI: string) {
// convert base64 to raw binary data held in a string
Expand Down Expand Up @@ -37,6 +37,7 @@ export class FileDownloadView extends InputWidgetView {

anchor_el: HTMLAnchorElement
button_el: HTMLButtonElement
input_el: HTMLInputElement // HACK: So this.input_el.id = "input" can be set in Bokeh 3.4
_downloadable: boolean = false
_click_listener: any
_prev_href: string | null = ""
Expand Down Expand Up @@ -75,10 +76,7 @@ export class FileDownloadView extends InputWidgetView {
}
}

render(): void {
super.render()
this.group_el.style.display = "flex"
this.group_el.style.alignItems = "stretch"
_render_input(): HTMLElement {
// Create an anchor HTML element that is styled as a bokeh button.
// When its 'href' and 'download' attributes are set, it's a downloadable link:
// * A click triggers a download
Expand Down Expand Up @@ -127,7 +125,14 @@ export class FileDownloadView extends InputWidgetView {
this.anchor_el.addEventListener("click", this._click_listener)
}
this.button_el.appendChild(this.anchor_el)
this.group_el.appendChild(this.button_el)
this.input_el = input() // HACK: So this.input_el.id = "input" can be set in Bokeh 3.4
return this.button_el
}

render(): void {
super.render()
this.group_el.style.display = "flex"
this.group_el.style.alignItems = "stretch"
}

stylesheets(): StyleSheetLike[] {
Expand Down
2 changes: 1 addition & 1 deletion panel/models/plotly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ export class PlotlyPlotView extends HTMLBoxView {
}

_get_trace(index: number, update: boolean): any {
const trace = clone(this.model.data[index]);
const trace = clone(this.model.data[index]) as any;
Copy link
Member Author

@hoxbro hoxbro Jan 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Else, it would give a type error.

const cds = this.model.data_sources[index];
for (const column of cds.columns()) {
let array = cds.get_array(column)[0];
Expand Down
3 changes: 2 additions & 1 deletion panel/models/reactive_html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ export class ReactiveHTMLView extends HTMLBoxView {
super.connect_signals()
this.connect(this.model.properties.children.change, async () => {
this.html = htmlDecode(this.model.html) || this.model.html
await this.rebuild()
await this.build_child_views()
this.invalidate_render()
})
this._recursive_connect(this.model.data, true, '')
this.connect(this.model.properties.events.change, () => {
Expand Down
7 changes: 4 additions & 3 deletions panel/models/singleselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export class SingleSelectView extends InputWidgetView {

render(): void {
super.render()
this.render_selection()
}

_render_input(): HTMLElement {
const options = this.model.options.map((opt) => {
let value, _label
if (isString(opt))
Expand All @@ -43,9 +46,7 @@ export class SingleSelectView extends InputWidgetView {
this.input_el.style.backgroundImage = 'none';

this.input_el.addEventListener("change", () => this.change_input())
this.group_el.appendChild(this.input_el)

this.render_selection()
return this.input_el
}

render_selection(): void {
Expand Down
Loading
Loading