Skip to content
Draft
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
18 changes: 12 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

SHINYLIVE_VERSION = $(shell node -p "require('./package.json').version")

PYODIDE_VERSION = 0.27.7
PYODIDE_VERSION = 314.0.7
PYODIDE_DIST_FILENAME = pyodide-$(PYODIDE_VERSION).tar.bz2
DOWNLOAD_DIR = ./downloads
R_SHINY_VERSION = 1.13.0.8000
Expand All @@ -45,7 +45,7 @@ FAICONS_WHEEL = faicons-$(FAICONS_VERSION)-py3-none-any.whl
# libsass is built in gadenbuie/libsass-python
# NOTE: Update https://github.com/gadenbuie/libsass-python/blob/dev/.github/workflows/pyodide.yml
# Pyodide, Emscripten, or Python versions change here.
LIBSASS_WHEEL=libsass-0.23.0-cp312-abi3-pyodide_2024_0_wasm32.whl
LIBSASS_WHEEL=libsass-0.23.0-cp314-abi3-pyemscripten_2026_0_wasm32.whl

VENV = venv
PYBIN = $(VENV)/bin
Expand Down Expand Up @@ -142,7 +142,7 @@ $(DOWNLOAD_DIR)/$(PYODIDE_DIST_FILENAME):

$(BUILD_DIR)/shinylive/pyodide: $(DOWNLOAD_DIR)/$(PYODIDE_DIST_FILENAME)
mkdir -p $(BUILD_DIR)/shinylive/pyodide
tar --exclude "*test*.tar" --exclude "node_modules" \
tar --exclude "*test*.tar" --exclude "*-tests.zip" --exclude "node_modules" \
-xvjf $(DOWNLOAD_DIR)/$(PYODIDE_DIST_FILENAME) \
-C $(BUILD_DIR)/shinylive

Expand Down Expand Up @@ -294,17 +294,23 @@ $(PACKAGE_DIR)/$(FAICONS_WHEEL): $(PYBIN) $(PACKAGE_DIR)/py-faicons
rm -f $(PACKAGE_DIR)/faicons*.whl
. $(PYBIN)/activate && cd $(PACKAGE_DIR)/py-faicons && pip wheel --no-deps -w ../ .

$(PACKAGE_DIR)/$(LIBSASS_WHEEL): $(PYBIN) $(PACKAGE_DIR)/$(LIBSASS_WHEEL)
$(PACKAGE_DIR)/$(LIBSASS_WHEEL): $(PYBIN)
rm -f $(PACKAGE_DIR)/libsass*.whl
curl --fail -L https://pkg.garrickadenbuie.com/libsass-python/$(LIBSASS_WHEEL) -o $(PACKAGE_DIR)/$(LIBSASS_WHEEL)

# The lock file reads the local wheels from $(PACKAGE_DIR), and expects exactly one
# wheel per package there. Building them first clears out older copies.
LOCAL_WHEELS = $(PACKAGE_DIR)/$(HTMLTOOLS_WHEEL) $(PACKAGE_DIR)/$(SHINY_WHEEL) \
$(PACKAGE_DIR)/$(SHINYWIDGETS_WHEEL) $(PACKAGE_DIR)/$(FAICONS_WHEEL) \
$(PACKAGE_DIR)/$(LIBSASS_WHEEL)

## Update the shinylive_lock.json file, based on shinylive_requirements.json
update_packages_lock: $(PYBIN) $(BUILD_DIR)/shinylive/pyodide
update_packages_lock: $(PYBIN) $(BUILD_DIR)/shinylive/pyodide $(LOCAL_WHEELS)
$(PYBIN)/pip install -r requirements-dev.txt
. $(PYBIN)/activate && scripts/pyodide_packages.py generate_lockfile

## Update the shinylive_lock.json file, but with local packages only
update_packages_lock_local: $(PYBIN) $(BUILD_DIR)/shinylive/pyodide
update_packages_lock_local: $(PYBIN) $(BUILD_DIR)/shinylive/pyodide $(LOCAL_WHEELS)
$(PYBIN)/pip install -r requirements-dev.txt
. $(PYBIN)/activate && scripts/pyodide_packages.py update_lockfile_local

Expand Down
2 changes: 1 addition & 1 deletion examples/python/plot_interact_exclude/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def plot1():
return (
ggplot(df_keep, aes("wt", "mpg"))
+ geom_point()
+ geom_point(data=df_exclude, color="#666", fill="white")
+ geom_point(data=df_exclude, color="#666666", fill="white")
+ geom_smooth(method="lm", fullrange=True)
)

Expand Down
14 changes: 9 additions & 5 deletions memory-bank/pythonPackageVersions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ One subcommand per Makefile target. All run inside `venv/` with `requirements-de

- `generate_lockfile` (`make update_packages_lock`) — reads every requirement. Local packages get
their info from the one wheel in `packages/` whose name starts with `<name>-` (exactly one must
exist), read with `pkginfo`. PyPI packages come from `https://pypi.org/pypi/<name>[/<version>]/json`;
exist), read with `pkginfo`. Both lock targets depend on those wheels in the Makefile
(`LOCAL_WHEELS`), and each wheel's rule removes older copies before building. PyPI packages come from `https://pypi.org/pypi/<name>[/<version>]/json`;
`_find_pypi_meta_with_wheel` takes the first `py3-none-any.whl`, and if the chosen release has
none, walks back to the newest release that does. `_recurse_dependencies_lockfile` then adds
each dependency that is not already in the lockfile or in the original Pyodide lock, always at
Expand All @@ -52,12 +53,15 @@ One subcommand per Makefile target. All run inside `venv/` with `requirements-de
`update_pyodide_pyodide_lock_json`) — loads the original Pyodide lock via
`orig_pyodide_lock()`, adds each lockfile package with `install_dir: "site"`, and computes the
SHA256 of local wheels from `packages/`. It then appends `EXTRA_DEPENDENCIES` (jinja2 for pandas,
exceptiongroup for anyio, setuptools for palmerpenguins) and drops `OMIT_DEPENDENCIES` (shiny
setuptools for palmerpenguins, anyio for Pyodide's starlette) and drops `OMIT_DEPENDENCIES` (shiny
from shinychat, to break a cycle). The result is written without indentation.

`orig_pyodide_lock()` keeps `pyodide-lock.orig.json` next to `pyodide-lock.json`. It copies the
current file over it when the copy is missing or when the `info.version` fields differ, so the
script can be run again without stacking additions.
`orig_pyodide_lock()` keeps `pyodide-lock.orig.json` next to `pyodide-lock.json`, so the script
can be run again without stacking additions. It copies the current file over it when the copy
is missing or when the current file has no `shiny` entry, which means Pyodide was just unpacked
(Pyodide 0.28 dropped `info.version`, so versions cannot be compared). This assumes Pyodide
never ships shiny. A current file that cannot be read raises an error rather than replacing
the saved copy.

Dependency filtering (`_filter_requires`): any requirement with a `;` marker is dropped, except
`platform_system == "Emscripten"` (kept for mizani's tzdata). Names in `AVOID_DEPEND_PACKAGES`
Expand Down
2 changes: 1 addition & 1 deletion scripts/create_typeshed.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pyright

# TODO: Automate version detection
PYODIDE_PYTHON_VERSION = "3.12"
PYODIDE_PYTHON_VERSION = "3.14"

# Packages that we'll create type stubs for.
PACKAGES = ("htmltools", "shiny", "shinywidgets", "shinyswatch")
Expand Down
19 changes: 10 additions & 9 deletions scripts/pyodide_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@
# doing table styling.
"jinja2",
],
# Can be removed when we moved to pyodide w/ python 3.11
"anyio": ["exceptiongroup"],
# palmerpenguins imports pkg_resources, which is part of setuptools.
"palmerpenguins": ["setuptools"],
# Pyodide 314's own starlette entry lists no dependencies, but it imports anyio.
"starlette": ["anyio"],
}

# Some packages may have a circular dependency. For example, shiny (v1.5.0) depends on
Expand Down Expand Up @@ -699,13 +699,14 @@ def orig_pyodide_lock() -> PyodidePackagesFile:
)
shutil.copy(pyodide_lock_json_file, orig_pyodide_lock_json_file)
else:
try:
with open(pyodide_lock_json_file, "r") as f_new, open(orig_pyodide_lock_json_file, "r") as f_orig:
new_info = json.load(f_new).get("info", {})
orig_info = json.load(f_orig).get("info", {})
if new_info.get("version") != orig_info.get("version"):
shutil.copy(pyodide_lock_json_file, orig_pyodide_lock_json_file)
except Exception:
# Pyodide 0.28 dropped `info.version`, and what is left is the same across
# patch releases. A pyodide-lock.json without shiny in it is a fresh one from
# a newly unpacked Pyodide, so it replaces the saved copy. This assumes
# Pyodide never ships shiny itself. An unreadable file raises rather than
# replacing the saved copy, which may be the only clean one left.
with open(pyodide_lock_json_file, "r") as f_new:
new_packages = json.load(f_new).get("packages", {})
if "shiny" not in new_packages:
shutil.copy(pyodide_lock_json_file, orig_pyodide_lock_json_file)

with open(orig_pyodide_lock_json_file, "r") as f:
Expand Down
Loading
Loading