Skip to content
File

Blob: build/python_metadata.bzl

8.0 KB
1# After updating this file, make sure to run "bazel mod tidy"
2load("@bazel_lib//lib:base64.bzl", "base64")
3load("@bazel_lib//lib:strings.bzl", "chr")
4load("//:build/python/packages_20240829_4.bzl", "PACKAGES_20240829_4")
5load("//:build/python/packages_20250808.bzl", "PACKAGES_20250808")
6 
7def _chunk(data, length):
8 return [data[i:i + length] for i in range(0, len(data), length)]
9 
10def hex_to_b64(hex):
11 s = ""
12 for chunk in _chunk(hex, 2):
13 s += chr(int(chunk, 16))
14 return "sha256-" + base64.encode(s)
15 
16PYODIDE_VERSIONS = [
17 {
18 "version": "0.26.0a2",
19 "sha256": "fbda450a64093a8d246c872bb901ee172a57fe594c9f35bba61f36807c73300d",
20 },
21 {
22 "version": "0.28.2",
23 "sha256": "c9f6dd067d119e50850849f7428e3c636ecbc2684a0d2ff992f3bd48a1062b6c",
24 },
25]
26 
27# This is the list of all the package metadata that we use.
28#
29# IMPORTANT: packages that are present here should never be removed after the package version is
30# released to the public. This is so that we don't break workers using those packages.
31#
32# ORDER MATTERS: the order of the keys in this dictionary matters, older package bundles should come
33# first.
34_package_lockfiles = [
35 PACKAGES_20240829_4,
36 PACKAGES_20250808,
37]
38 
39# The below is a list of pyodide-lock.json files for each package bundle version that we support.
40# Each of these gets embedded in the workerd and EW binary.
41PYTHON_LOCKFILES = [meta["info"] for meta in _package_lockfiles]
42 
43# Used to generate the import tests, where we import each top level name from each package and check
44# that it doesn't fail.
45PYTHON_IMPORTS_TO_TEST = {meta["info"]["tag"]: meta["import_tests"] for meta in _package_lockfiles}
46 
47# Each new package bundle should contain the same packages as the previous. We verify this
48# constraint here.
49def verify_no_packages_were_removed():
50 for curr_info, next_info in zip(_package_lockfiles[:-1], _package_lockfiles[1:]):
51 curr_pkgs = curr_info["import_tests"]
52 next_pkgs = next_info["import_tests"]
53 missing_pkgs = [pkg for pkg in curr_pkgs if pkg not in next_pkgs]
54 if missing_pkgs:
55 fail("Some packages from version ", curr_info["info"]["tag"], " missing in version", next_info["info"]["tag"], ":\n", " ", ", ".join(missing_pkgs), "\n\n")
56 
57verify_no_packages_were_removed()
58 
59def _bundle_id(*, pyodide_version, pyodide_date, backport, **_kwds):
60 return "%s_%s_%s" % (pyodide_version, pyodide_date, backport)
61 
62def _add_integrity(entry):
63 for key, value in entry.items():
64 if not key.endswith("_hash"):
65 continue
66 newkey = key.removesuffix("_hash") + "_integrity"
67 entry[newkey] = hex_to_b64(value)
68 
69def _make_vendored_packages(entry):
70 if entry["name"] == "development":
71 return
72 vendor_tests = {}
73 for e in entry["vendored_packages_for_tests"]:
74 vendor_tests[e["name"]] = e
75 entry["vendored_packages_for_tests"] = vendor_tests
76 
77def _check_pyodide_versions(version_info):
78 pyodide_versions = {ver["version"]: 1 for ver in PYODIDE_VERSIONS}
79 pyodide_versions["dev"] = 1
80 for entry in version_info.values():
81 if entry["pyodide_version"] not in pyodide_versions:
82 fail("Version %s of Pyodide not in PYODIDE_VERSIONS" % entry["pyodide_version"])
83 
84def _make_bundle_version_info(versions):
85 result = {}
86 for entry in versions:
87 name = entry["name"]
88 if name != "development":
89 entry["id"] = _bundle_id(**entry)
90 entry["real_pyodide_version"] = entry["pyodide_version"]
91 entry["feature_flags"] = [entry["flag"]]
92 entry["feature_string_flags"] = [entry["enable_flag_name"]]
93 if "packages" in entry:
94 entry["packages"] = entry["packages"]["info"]["tag"]
95 _add_integrity(entry)
96 result[name] = entry
97 _make_vendored_packages(entry)
98 
99 dev = result["development"]
100 
101 # Uncomment to test with development = 0.26.0a2
102 # dev["real_pyodide_version"] = "0.26.0a2"
103 result["development"] = result[dev["real_pyodide_version"]] | dev
104 _check_pyodide_versions(result)
105 return result
106 
107VENDORED_VERSION_INDEPENDENT = [
108 {
109 # Downloaded from https://pub-25a5b2f2f1b84655b185a505c7a3ad23.r2.dev/beautifulsoup4-vendored-for-ew-testing.zip
110 "name": "beautifulsoup4",
111 "abi": None,
112 "sha256": "5aa09c5f549443969dda260a70e58e3ac8537bd3d29155b307a3d98b36eb70fd",
113 },
114 {
115 "name": "pytest-asyncio",
116 "abi": None,
117 "sha256": "be25b788392d124cbdfbb9b3d13541da69a7b6b977bc9474dddaddeaab6421b4",
118 },
119 {
120 "name": "python-workers-runtime-sdk",
121 "abi": None,
122 "sha256": "fc4fb50f73973c257277155b3cb113aa2cf68e9da8ef424ecb049b41bc463183",
123 },
124]
125 
126BUNDLE_VERSION_INFO = _make_bundle_version_info([
127 {
128 "name": "0.26.0a2",
129 "released": True,
130 "pyodide_version": "0.26.0a2",
131 "pyodide_date": "2024-03-01",
132 "packages": PACKAGES_20240829_4,
133 "backport": "79",
134 "integrity": "sha256-LO3jNW3PXEiwHm10GgnssxwKw+v37KMGZBiBwjUReVk=",
135 "flag": "pythonWorkers",
136 "enable_flag_name": "python_workers",
137 "emscripten_version": "3.1.52",
138 "python_version": "3.12.1",
139 "baseline_snapshot": "baseline-61eedf943.bin",
140 "baseline_snapshot_hash": "61eedf9432d635bdf091b26efece020b3543429a609fad7af9e8d4de2ec44f47",
141 "numpy_snapshot": "ew-py-package-snapshot_numpy-v2.bin",
142 "numpy_snapshot_hash": "5055deb53f404afacba73642fd10e766b123e661847e8fdf4f1ec92d8ca624dc",
143 "fastapi_snapshot": "ew-py-package-snapshot_fastapi-v2.bin",
144 "fastapi_snapshot_hash": "d204956a074cd74f7fe72e029e9a82686fcb8a138b509f765e664a03bfdd50fb",
145 "vendored_packages_for_tests": VENDORED_VERSION_INDEPENDENT + [
146 {
147 # Downloaded from https://pub-25a5b2f2f1b84655b185a505c7a3ad23.r2.dev/fastapi-312-vendored-for-ew-testing.zip
148 "name": "fastapi",
149 "abi": "3.12",
150 "sha256": "5e6e21dbeda7c1eaadb99e6e52aa2ce45325b51e9a417198701e68e0cfd12a4c",
151 },
152 {
153 "name": "scipy",
154 "abi": "3.12",
155 "sha256": "787e45be6969a5609093b3df9cc2dba2afec9e10bace977f5045697cc329aa7c",
156 },
157 ],
158 },
159 {
160 "name": "0.28.2",
161 "released": True,
162 "pyodide_version": "0.28.2",
163 "pyodide_date": "2025-01-16",
164 "packages": PACKAGES_20250808,
165 "backport": "10",
166 "integrity": "sha256-k37ELtvRw8fd3QHsMgja0Tl+4QKP1qGTnNdjxUiqb2E=",
167 "flag": "pythonWorkers20250116",
168 "enable_flag_name": "python_workers_20250116",
169 "emscripten_version": "4.0.9",
170 "python_version": "3.13.2",
171 "baseline_snapshot": "baseline-4569679fb.bin",
172 "baseline_snapshot_hash": "4569679fb78a3c5c8dbfa73d57c61c6a5394617632fbac7b5873ba322c85463d",
173 "numpy_snapshot": "package_snapshot_numpy-60c9cb28e.bin",
174 "numpy_snapshot_hash": "60c9cb28e6dc1ea6ab38b25471ddaa315b667637c9dd6f94aceb2acc6519c623",
175 "fastapi_snapshot": "package_snapshot_fastapi-a6ccb56fe.bin",
176 "fastapi_snapshot_hash": "a6ccb56fe9eac265d139727d0134e8d6432c5fe25c8c0b8ec95252b13493b297",
177 "dedicated_fastapi_snapshot": "snapshot_a6b652a95810783f5078b9a5dbd4a07c30718acb4ff724e82c25db7353dd7f2d.bin",
178 "dedicated_fastapi_snapshot_hash": "4af6f012a5fb32f31a426e6f109e88ae85b18ee3dd131e1caaaad989cd962bbe",
179 "vendored_packages_for_tests": VENDORED_VERSION_INDEPENDENT + [
180 {
181 "name": "fastapi",
182 "abi": "3.13",
183 "sha256": "955091f1bd2eb33255ff2633df990bedc96e2f6294e78f2b416078777394f942",
184 },
185 {
186 "name": "shapely",
187 "abi": "3.13",
188 "sha256": "2e5c462cb32ee8697b3647dfc9d5c88dcdfd0702da34a2d7dc6b07b8090dd321",
189 },
190 ],
191 },
192 {
193 "real_pyodide_version": "0.28.2",
194 "name": "development",
195 "pyodide_version": "dev",
196 "pyodide_date": "dev",
197 "id": "dev",
198 "flag": "pythonWorkersDevPyodide",
199 "enable_flag_name": "python_workers_development",
200 },
201])