Skip to content

Commit 7e0e20c

Browse files
Add script to auto-update version properly (and release bokeh version 3.6.2) (#9)
* Add script to auto-update version properly
1 parent 6f56271 commit 7e0e20c

File tree

15 files changed

+266
-25
lines changed

15 files changed

+266
-25
lines changed

.github/workflows/enforce-pre-commit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@ jobs:
5252
- name: Install prettier
5353
run: cd streamlit_bokeh/frontend && npm install
5454
- name: Run pre-commit hooks
55-
run: PRE_COMMIT_NO_CONCURRENCY=true pre-commit run --show-diff-on-failure --color=always
55+
run: PRE_COMMIT_NO_CONCURRENCY=true pre-commit run --show-diff-on-failure --color=always --all-files

e2e_playwright/bokeh_chart_basics_test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020

2121
@pytest.mark.parametrize("chart", CHART_TYPES)
22-
def test_bokeh_chart(themed_app: Page, assert_snapshot: ImageCompareFunction, chart: str):
22+
def test_bokeh_chart(
23+
themed_app: Page, assert_snapshot: ImageCompareFunction, chart: str
24+
):
2325
"""Test that st.bokeh_chart renders correctly."""
2426
themed_app.get_by_test_id("stSelectbox").locator("input").click()
2527

e2e_playwright/conftest.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import subprocess
3333
import sys
3434
import time
35-
from dataclasses import dataclass
3635
from io import BytesIO
3736
from pathlib import Path
3837
from random import randint
@@ -48,8 +47,6 @@
4847
FrameLocator,
4948
Locator,
5049
Page,
51-
Response,
52-
Route,
5350
)
5451
from pytest import FixtureRequest
5552

e2e_playwright/test-requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
bokeh==3.6.1
14+
bokeh==3.6.2
1515
bokeh-sampledata
1616
pixelmatch>=0.3.0,<1.0.0
1717
playwright==1.49.*
@@ -20,4 +20,4 @@ pytest-playwright>=0.3.3
2020
pytest-xdist
2121
scipy
2222
testfixtures
23-
dist/streamlit_bokeh-3.6.0-py3-none-any.whl
23+
dist/streamlit_bokeh-3.6.1-py3-none-any.whl

scripts/update_bokeh_version.py

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import re
17+
import requests
18+
import semver
19+
20+
SETUP_PY_PATH = "setup.py"
21+
22+
23+
def get_latest_bokeh_version():
24+
url = "https://pypi.org/pypi/bokeh/json"
25+
response = requests.get(url)
26+
response.raise_for_status() # Raises an HTTPError if the status is not 200
27+
data = response.json()
28+
# This field will provide the latest stable version
29+
return data["info"]["version"]
30+
31+
32+
def get_component_version():
33+
with open(SETUP_PY_PATH, "r") as f:
34+
setup_content = f.read()
35+
36+
# Extract version from setup.py
37+
match = re.search(r"version\s*=\s*['\"]([\d\.]+)(['\"])", setup_content)
38+
39+
if match:
40+
return match.group(1)
41+
else:
42+
raise ValueError("Bokeh version not found in the file")
43+
44+
45+
def get_dependency_bokeh_version():
46+
with open(SETUP_PY_PATH, "r") as f:
47+
setup_content = f.read()
48+
49+
# Extract Bokeh version from dependency line (e.g., bokeh==2.4.3)
50+
match = re.search(r"bokeh\s*==\s*([\d\.]+)", setup_content)
51+
52+
if match:
53+
return match.group(1)
54+
else:
55+
raise ValueError("Bokeh version not found in the file")
56+
57+
58+
def download_files(new_version, destination):
59+
files_to_download = [
60+
f"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-{new_version}.min.js",
61+
f"https://cdn.bokeh.org/bokeh/release/bokeh-gl-{new_version}.min.js",
62+
f"https://cdn.bokeh.org/bokeh/release/bokeh-api-{new_version}.min.js",
63+
f"https://cdn.bokeh.org/bokeh/release/bokeh-tables-{new_version}.min.js",
64+
f"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-{new_version}.min.js",
65+
f"https://cdn.bokeh.org/bokeh/release/bokeh-{new_version}.min.js",
66+
]
67+
68+
for url in files_to_download:
69+
filename = os.path.basename(url)
70+
print(f"Downloading {filename}")
71+
r = requests.get(url, stream=True)
72+
r.raise_for_status()
73+
with open(os.path.join(destination, "bokeh", filename), "wb") as f:
74+
for chunk in r.iter_content(chunk_size=8192):
75+
f.write(chunk)
76+
77+
78+
def update_setup_py(new_version, old_bokeh_version, new_bokeh_version):
79+
with open(SETUP_PY_PATH, "r") as f:
80+
setup_content = f.read()
81+
82+
# Replace package version in `version='...'`
83+
# This pattern is naive; adapt as needed for your file structure.
84+
setup_content = re.sub(
85+
r"(version\s*=\s*['\"])([\d\.]+)(['\"])",
86+
rf"\g<1>{new_version}\g<3>",
87+
setup_content,
88+
)
89+
90+
# Replace bokeh==old_version with bokeh==new_version
91+
if old_bokeh_version:
92+
setup_content = re.sub(
93+
rf"(bokeh\s*==\s*){old_bokeh_version}",
94+
rf"\g<1>{new_bokeh_version}",
95+
setup_content,
96+
)
97+
98+
with open(SETUP_PY_PATH, "w") as f:
99+
f.write(setup_content)
100+
101+
102+
def update_test_requirements(
103+
old_bokeh_version, new_bokeh_version, old_version, new_version
104+
):
105+
test_requirements_path = "e2e_playwright/test-requirements.txt"
106+
with open(test_requirements_path, "r") as f:
107+
test_requirements_contents = f.read()
108+
109+
# Replace bokeh==old_bokeh_version with bokeh==new_bokeh_version
110+
if old_bokeh_version:
111+
test_requirements_contents = re.sub(
112+
rf"(bokeh\s*==\s*){old_bokeh_version}",
113+
rf"\g<1>{new_bokeh_version}",
114+
test_requirements_contents,
115+
)
116+
117+
test_requirements_contents = re.sub(
118+
rf"(dist/streamlit_bokeh-){old_version}(-py3-none-any.whl)",
119+
rf"\g<1>{new_version}\g<2>",
120+
test_requirements_contents,
121+
)
122+
123+
with open(test_requirements_path, "w") as f:
124+
f.write(test_requirements_contents)
125+
126+
127+
def update_package_json(old_version, new_version):
128+
package_json_path = "streamlit_bokeh/frontend/package.json"
129+
with open(package_json_path, "r") as f:
130+
package_json_contents = f.read()
131+
132+
# Replace bokeh==old_version with bokeh==new_version
133+
if old_version:
134+
package_json_contents = re.sub(
135+
rf"(\"version\": \"){old_version}(\")",
136+
rf"\g<1>{new_version}\g<2>",
137+
package_json_contents,
138+
)
139+
140+
with open(package_json_path, "w") as f:
141+
f.write(package_json_contents)
142+
143+
144+
def update_init_py(old_bokeh_version, new_bokeh_version):
145+
init_py_path = "streamlit_bokeh/__init__.py"
146+
with open(init_py_path, "r") as f:
147+
init_py_contents = f.read()
148+
149+
# Replace bokeh==old_bokeh_version with bokeh==new_bokeh_version
150+
if old_bokeh_version:
151+
init_py_contents = re.sub(
152+
rf"(REQUIRED_BOKEH_VERSION = \"){old_bokeh_version}(\")",
153+
rf"\g<1>{new_bokeh_version}\g<2>",
154+
init_py_contents,
155+
)
156+
157+
with open(init_py_path, "w") as f:
158+
f.write(init_py_contents)
159+
160+
161+
def update_index_html(public_dir, old_version, new_version):
162+
index_html_path = os.path.join(public_dir, "index.html")
163+
if os.path.exists(index_html_path):
164+
with open(index_html_path, "r", encoding="utf-8") as f:
165+
html_content = f.read()
166+
167+
# If old_version is known, do a direct replacement
168+
if old_version:
169+
# Replace each script reference with the new version
170+
cdn_suffixes = ["mathjax", "gl", "api", "tables", "widgets", ""]
171+
for suffix in cdn_suffixes:
172+
old_str = (
173+
f"bokeh-{suffix}-{old_version}.min.js"
174+
if suffix
175+
else f"bokeh-{old_version}.min.js"
176+
)
177+
new_str = (
178+
f"bokeh-{suffix}-{new_version}.min.js"
179+
if suffix
180+
else f"bokeh-{new_version}.min.js"
181+
)
182+
html_content = html_content.replace(old_str, new_str)
183+
184+
with open(index_html_path, "w", encoding="utf-8") as f:
185+
f.write(html_content)
186+
else:
187+
print("No index.html found in frontend/public. Skipping HTML update.")
188+
189+
190+
if __name__ == "__main__":
191+
new_bokeh_version = get_latest_bokeh_version()
192+
new_bokeh_version_semver = semver.Version.parse(new_bokeh_version)
193+
old_bokeh_version = get_dependency_bokeh_version()
194+
195+
old_version = get_component_version()
196+
old_version_semver = semver.Version.parse(old_version)
197+
198+
new_version = f"{new_bokeh_version_semver.major}.{new_bokeh_version_semver.minor}.{old_version_semver.patch + 1}"
199+
if (
200+
old_version_semver.major != new_bokeh_version_semver.major
201+
or old_version_semver.minor != new_bokeh_version_semver.minor
202+
):
203+
new_version = (
204+
f"{new_bokeh_version_semver.major}.{new_bokeh_version_semver.minor}.0"
205+
)
206+
207+
print(f"Current local bokeh version: {old_bokeh_version}")
208+
print(f"Latest PyPI bokeh version: {new_bokeh_version}")
209+
print(f"Current component version: {old_version}")
210+
print(f"Latest component version: {new_version}")
211+
212+
if new_bokeh_version == old_bokeh_version:
213+
print("No new version available")
214+
print("::set-output name=needs_update::false")
215+
exit(0)
216+
217+
print("New version available!")
218+
public_dir = "streamlit_bokeh/frontend/public"
219+
220+
# Remove original files
221+
bokeh_dir = os.path.join(public_dir, "bokeh")
222+
for filename in os.listdir(bokeh_dir):
223+
if "bokeh" in filename and filename.endswith(".js"):
224+
os.remove(os.path.join(bokeh_dir, filename))
225+
226+
download_files(new_bokeh_version, public_dir)
227+
# Update the bokeh dependency version in index.html and __init__.py
228+
update_index_html(public_dir, old_bokeh_version, new_bokeh_version)
229+
update_init_py(old_bokeh_version, new_bokeh_version)
230+
231+
# Update the bokeh dependency version and component version in setup.py and test-requirements.txt
232+
update_setup_py(new_version, old_bokeh_version, new_bokeh_version)
233+
update_test_requirements(
234+
old_bokeh_version, new_bokeh_version, old_version, new_version
235+
)
236+
237+
# Update the component version in package.json
238+
update_package_json(old_version, new_version)
239+
240+
print("::set-output name=needs_update::true")
241+
print(f"::set-output name=old_version::{old_version}")
242+
print(f"::set-output name=new_version::{new_version}")

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
setuptools.setup(
2323
name="streamlit-bokeh",
24-
version="3.6.0",
24+
version="3.6.1",
2525
author="Streamlit",
2626
author_email="[email protected]",
2727
description="Streamlit component that allows you to render Bokeh charts",
@@ -37,7 +37,7 @@
3737
# If your component has other Python dependencies, list
3838
# them here.
3939
"streamlit>=1.26",
40-
"bokeh==3.6.1",
40+
"bokeh==3.6.2",
4141
],
4242
extras_require={
4343
"devel": [

streamlit_bokeh/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
from bokeh.plotting.figure import Figure
6262

6363
__version__ = importlib.metadata.version("streamlit_bokeh")
64-
REQUIRED_BOKEH_VERSION = "3.6.1"
64+
REQUIRED_BOKEH_VERSION = "3.6.2"
6565

6666

6767
def streamlit_bokeh(

streamlit_bokeh/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "streamlit_bokeh",
3-
"version": "3.6.0",
3+
"version": "3.6.1",
44
"private": true,
55
"dependencies": {
66
"@types/jest": "^24.0.0",

0 commit comments

Comments
 (0)