From 7b497d48bd5dad27c8bf4843ce196e680d8b3caf Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Tue, 13 Jan 2026 08:59:26 +0900 Subject: [PATCH] Use latest Pyodide version for each python version (#17372) ## Summary This changes how the `download-metadata.json` file is generated for Pyodide. Previously, if we have a different Pyodide version with a same Python version, the older Pyodide version is selected. For example, say we have - Pyodide 0.29.0 with Python 3.13.2 - Pyodide 0.28.3 with Python 3.13.2 then, pyodide 0.28.3 was stored in `download-metadata.json` as we iterate in decending order with overwriting the value that was previously written. I fixed it by picking up the latest Pyodide version for each Python version. ## Test Plan Ran `uv run -- crates/uv-python/fetch-download-metadata.py` locally, and verified the output: ``` 2026-01-09 15:39:23 INFO Fetching Pyodide checksums: 0/4 2026-01-09 15:39:24 INFO Selected cpython-3.13.2-emscripten-wasm32-musl (0.29.1) 2026-01-09 15:39:24 INFO Selected cpython-3.12.7-emscripten-wasm32-musl (0.27.7) 2026-01-09 15:39:24 INFO Selected cpython-3.12.1-emscripten-wasm32-musl (0.26.4) 2026-01-09 15:39:24 INFO Selected cpython-3.11.3-emscripten-wasm32-musl (0.25.1) ``` --- crates/uv-python/fetch-download-metadata.py | 40 ++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/crates/uv-python/fetch-download-metadata.py b/crates/uv-python/fetch-download-metadata.py index f12bd012e..9bf88e7df 100755 --- a/crates/uv-python/fetch-download-metadata.py +++ b/crates/uv-python/fetch-download-metadata.py @@ -597,41 +597,41 @@ class PyodideFinder(Finder): releases = release_resp.json() metadata = meta_resp.json()["releases"] - maj_minor_seen = set() - results = [] + results = {} for release in releases: pyodide_version = release["tag_name"] meta = metadata.get(pyodide_version, None) if meta is None: continue - maj_min = pyodide_version.rpartition(".")[0] - # Only keep latest - if maj_min in maj_minor_seen: - continue - maj_minor_seen.add(maj_min) - python_version = Version.from_str(meta["python_version"]) + # Find xbuildenv asset for asset in release["assets"]: if asset["name"].startswith("xbuildenv"): break + else: + # not found: should not happen but just in case + continue url = asset["browser_download_url"] - results.append( - PythonDownload( - release=0, - version=python_version, - triple=self.TRIPLE, - flavor=pyodide_version, - implementation=self.implementation, - filename=asset["name"], - url=url, - build=pyodide_version, - ) + download = PythonDownload( + release=0, + version=python_version, + triple=self.TRIPLE, + flavor=pyodide_version, + implementation=self.implementation, + filename=asset["name"], + url=url, + build=pyodide_version, ) - return results + # Only keep latest Pyodide version of each Python version + # arch/platform are all the same for Pyodide (wasm32, emscripten) + if python_version not in results: + results[python_version] = download + + return list(results.values()) async def _fetch_checksums(self, downloads: list[PythonDownload], n: int) -> None: for idx, batch in enumerate(batched(downloads, n)):