Skip to content

Conversation

sfc-gh-kmcgrady
Copy link
Collaborator

@sfc-gh-kmcgrady sfc-gh-kmcgrady commented Jan 17, 2025

This PR intrroduces the bokeh chart in its entirety for release.

We are deliberately releasing 3.6.1 in order to test out the auto update functionality.

The component is simple avoiding react and making it a pure JS app.

Recommendation to Reviewers: Feel free to give format suggestions, though the next PR #5 focuses on the formatting fixes.

setup.py Outdated

setuptools.setup(
name="streamlit-bokeh",
version="3.6.1",

Choose a reason for hiding this comment

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

just sanity-check: was your idea to follow the bokeh versioning? So when bokeh is updated, we also bump this version to the same one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's the current plan. But I am reconsidering it now if there's a issue and we need to issue a patch. Let me think a little bit more.

Choose a reason for hiding this comment

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

Yeah good point, I think it might make sense to use our own versioning. Not only for patches, but perhaps we change something with the (internal) API or whatever and then we might run into issues. So decoupling the versions might make sense

Choose a reason for hiding this comment

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

I think we could try to match only the major and minor versions of bokeh and keep the patch version for ourselves.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I like that. Will adjust to 3.6.0

setup.py Outdated
# By definition, a Custom Component depends on Streamlit.
# If your component has other Python dependencies, list
# them here.
"streamlit >= 0.63",

Choose a reason for hiding this comment

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

I am wondering whether we should be way more strict. While technical apparently possible, would we really want to enable such an old version to work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It would help with adoptability, but we can also try doing 1.26.0+ for partners' sake?

Choose a reason for hiding this comment

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

sounds good!

Copy link

@sfc-gh-braethlein sfc-gh-braethlein Jan 20, 2025

Choose a reason for hiding this comment

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

We cannot re-use the font files that already come bundled with Streamlit because we are in an iframe, can we?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The answer is yes unfortunately. We could hard code the parent frame's URL which enables caching, but that would be more brittle should Streamlit adjust the location and naming.

Choose a reason for hiding this comment

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

Too bad! I agree, the alternative sounds too brittle!

<!DOCTYPE html>
<html lang="en">
<head>
<title>Streamlit Component</title>
Copy link

@sfc-gh-braethlein sfc-gh-braethlein Jan 20, 2025

Choose a reason for hiding this comment

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

nit: better title might a "Streamlit Bokeh Chart"

Comment on lines 91 to 93
// embed_item is actually an async function call, so a race condition
// can occur if updateChart is called twice, leading to two Bokeh charts
// to be embedded at the same time.

Choose a reason for hiding this comment

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

but this cannot happen here because we use await? Should we have a lock or something indicating that the function was called?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah yes, we can probably remove the comment now.

Comment on lines 117 to 124
const renderedAppTheme = JSON.stringify(renderData.theme)

let themeChanged = false
if (
renderData.args.bokeh_theme !== currentTheme ||
appTheme !== renderedAppTheme
) {
currentTheme = renderData.args.bokeh_theme

Choose a reason for hiding this comment

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

Could you elaborate a little bit please why there are two ways of passing a theme to the chart? renderData.args.bokeh_theme seems to come from the Python side, right? Where does renderData.themecome from?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

renderData.theme is the theme that comes from Streamlit (so if I switch light theme to dark theme) renderData.theme changes. I probably should make this more efficient and specify if the bokeh theme changed or the bokeh theme is "streamlit" and the rendered theme has changed. I'll fix that.

Comment on lines 129 to 137
if (currentTheme === "streamlit") {
use_theme(streamlitTheme(renderData.theme as Theme))
themeChanged = true
} else if (currentTheme in window.Bokeh.Themes) {
use_theme(window.Bokeh.Themes[currentTheme])
} else {
use_theme(streamlitTheme(renderData.theme as Theme))
themeChanged = true
}

Choose a reason for hiding this comment

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

I would change this to:

  if (currentTheme === "streamlit" || !(currentTheme in window.Bokeh.Themes)) {
    use_theme(streamlitTheme(renderData.theme as Theme))
    themeChanged = true
  } else {
    use_theme(window.Bokeh.Themes[currentTheme])
  }

In my opinion this makes it more obvious that the first and third case perform the identical operation.

// Python script.

// We tell Streamlit to update our frameHeight after each render event, in
// case it has changed. (This isn't strictly necessary for the example

Choose a reason for hiding this comment

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

still, why not move it into the if(hasChanged || themeChanged) block?

Comment on lines 120 to 123
if (
renderData.args.bokeh_theme !== currentTheme ||
appTheme !== renderedAppTheme
) {

Choose a reason for hiding this comment

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

nit: it might be cleaner to move the theme logic to its own function so that onRender is more dense

Choose a reason for hiding this comment

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

Can the file be removed?

Also, was the idea to not use React to have one dependency less we have to maintain?

Copy link
Collaborator Author

@sfc-gh-kmcgrady sfc-gh-kmcgrady Jan 20, 2025

Choose a reason for hiding this comment

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

I'll check. It came from the template, so I assumed it was necessary. And yes. Since Bokeh doesn't come in a nice react component, and we do minimal processing. I figured it was simpler to just use vanilla JS. Should be faster.

}

export function streamlitTheme(theme: Theme): BokehTheme {
// @ts-expect-error fadedText10 is not defined in the Theme type
Copy link

@sfc-gh-braethlein sfc-gh-braethlein Jan 20, 2025

Choose a reason for hiding this comment

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

its not defined, but set by our streamlit-component-lib? In this case, instead of expecting this error, perhaps this should be fixed in the Theme of streamlit-component-lib instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll double check with @sfc-gh-lmasuch since this is tied to the advanced theming (also a note to make sure the advanced theming is included in the minimum version we require.

Choose a reason for hiding this comment

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

oh yeah, checking the minimal version is a good aspect!

Copy link

@sfc-gh-lmasuch sfc-gh-lmasuch Jan 21, 2025

Choose a reason for hiding this comment

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

Yeah, I think we eventually need to officially expose colors that are generated from theme variables as well to custom components. But not sure if fadedText10 will be something that stays forever. Maybe its a bit safer to actually create this color manually here: transparentize(textColor, 0.8). fadedText10 is something that could be removed at any time -> which probably will break this custom component

"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"

Choose a reason for hiding this comment

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

we don't seem to use React in this repo

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will remove.

Copy link

@sfc-gh-braethlein sfc-gh-braethlein left a comment

Choose a reason for hiding this comment

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

How do you feel about adding a couple of unit tests for the functions in index.ts (getChartData (and the fact that it is memoized), an extracted processTheme function, ...) ? I know you have added e2e tests in #6, but for fast and general testing it could make test.

if TYPE_CHECKING:
from bokeh.plotting.figure import Figure

ST_BOKEH_VERSION = importlib.metadata.version("streamlit_bokeh")

Choose a reason for hiding this comment

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

nit: should we also expose this under __version__ here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will make this version. Though with the new convention, I opted to hard code the dependency version for simplicity. The update script will update everything.


ST_BOKEH_VERSION = importlib.metadata.version("streamlit_bokeh")

def streamlit_bokeh(figure: "Figure", use_container_width=True, theme: str = "streamlit", key=None):
Copy link

@sfc-gh-lmasuch sfc-gh-lmasuch Jan 21, 2025

Choose a reason for hiding this comment

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

the types of use_container_width and key + the return type is missing here

setup.py Outdated
packages=setuptools.find_packages(),
include_package_data=True,
classifiers=[],
python_requires=">=3.10",

Choose a reason for hiding this comment

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

nit: is it also possible to support python 3.9 since this is also still supported with Streamlit?

@@ -1,2 +1,3 @@
# streamlit-bokeh-chart
# streamlit-bokeh

Choose a reason for hiding this comment

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

nit: we might want to add a bit more info here, but that's probably a follow up or something to get Debbie involved in.

Comment on lines 19 to 21
// See https://github.com/bokeh/bokeh/blob/3.6.2/bokehjs/src/lib/models/plots/plot.ts#L203
const DEFAULT_WIDTH = 600 // px
const DEFAULT_HEIGHT = 600 // px

Choose a reason for hiding this comment

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

nit: The default width & height we use for vega charts is 400 x 350 (not sure about plotly). No strong opinion, but maybe it makes sense to use similar numbers for bokeh.

Copy link

@sfc-gh-lmasuch sfc-gh-lmasuch left a comment

Choose a reason for hiding this comment

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

LGTM 👍 added a couple of minor comments.

@sfc-gh-lmasuch
Copy link

sfc-gh-lmasuch commented Jan 22, 2025

Two changes that might be worth doing:

  • Add types for streamlit_bokeh
  • Use transparentize(textColor, 0.8) instead of fadedText10 to avoid breakage.

@sfc-gh-kmcgrady sfc-gh-kmcgrady merged commit 590b9a4 into main Jan 22, 2025
4 checks passed
@sfc-gh-kmcgrady sfc-gh-kmcgrady deleted the feature/bokeh_chart branch January 22, 2025 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants