diff --git a/src/pyodide/internal/metadata.ts b/src/pyodide/internal/metadata.ts index 256b2544757..aabdc6356ea 100644 --- a/src/pyodide/internal/metadata.ts +++ b/src/pyodide/internal/metadata.ts @@ -65,11 +65,10 @@ const FORCE_NEW_VENDOR_PATH: boolean = !!COMPATIBILITY_FLAGS.python_workers_force_new_vendor_path; export const IS_DEDICATED_SNAPSHOT_ENABLED: boolean = !!COMPATIBILITY_FLAGS.python_dedicated_snapshot; -const EXTERNAL_SDK = !!COMPATIBILITY_FLAGS.enable_python_external_sdk; +export const EXTERNAL_SDK = !!COMPATIBILITY_FLAGS.enable_python_external_sdk; export const LEGACY_GLOBAL_HANDLERS = !NO_GLOBAL_HANDLERS; export const LEGACY_VENDOR_PATH = !FORCE_NEW_VENDOR_PATH; -export const LEGACY_INCLUDE_SDK = !EXTERNAL_SDK; export const CHECK_RNG_STATE = !!COMPATIBILITY_FLAGS.python_check_rng_state; export const setCpuLimitNearlyExceededCallback = diff --git a/src/pyodide/python-entrypoint-helper.ts b/src/pyodide/python-entrypoint-helper.ts index 60b29ba6f61..7ade0357359 100644 --- a/src/pyodide/python-entrypoint-helper.ts +++ b/src/pyodide/python-entrypoint-helper.ts @@ -13,7 +13,7 @@ import { COMPATIBILITY_FLAGS, IS_WORKERD, LEGACY_GLOBAL_HANDLERS, - LEGACY_INCLUDE_SDK, + EXTERNAL_SDK, LOCKFILE, MAIN_MODULE_NAME, SHOULD_SNAPSHOT_TO_DISK, @@ -200,6 +200,24 @@ async function applyPatch(pyodide: Pyodide, patchName: string): Promise { } async function injectWorkersApi(pyodide: Pyodide): Promise { + if (EXTERNAL_SDK) { + pyodide.FS.mkdir(`${pyodide.FS.sitePackages}/workers`); + const template = [ + `err = ModuleNotFoundError("No module named '$MODNAME'", name="$MODNAME")`, + `err.add_note("You need to update to workers-py >= 1.90 or to pass disable_python_external_sdk")`, + `raise err`, + ].join('\n'); + pyodide.FS.writeFile( + `${pyodide.FS.sitePackages}/workers/__init__.py`, + template.replaceAll('$MODNAME', 'workers') + ); + pyodide.FS.writeFile( + `${pyodide.FS.sitePackages}/asgi.py`, + template.replaceAll('$MODNAME', 'asgi') + ); + return; + } + const sitePackages = pyodide.FS.sitePackages; if (pyodide.version === PyodideVersion.V0_26_0a2) { // Inject at cloudflare.workers for backwards compatibility @@ -250,9 +268,7 @@ async function setupPatches(pyodide: Pyodide): Promise { pyodide.registerJsModule('_cloudflare_compat_flags', COMPATIBILITY_FLAGS); // Inject modules that enable JS features to be used idiomatically from Python. - if (LEGACY_INCLUDE_SDK) { - await injectWorkersApi(pyodide); - } + await injectWorkersApi(pyodide); // Install patches as needed if (TRANSITIVE_REQUIREMENTS.has('aiohttp')) { diff --git a/src/pyodide/types/filesystem.d.ts b/src/pyodide/types/filesystem.d.ts index 0eeae73b76b..1aac126188f 100644 --- a/src/pyodide/types/filesystem.d.ts +++ b/src/pyodide/types/filesystem.d.ts @@ -29,7 +29,11 @@ interface FSLookupResult { interface FS { mkdir: (dirname: string) => void; mkdirTree: (dirname: string) => void; - writeFile: (fname: string, contents: Uint8Array, options: object) => void; + writeFile: ( + fname: string, + contents: Uint8Array | string, + options?: { canOwn: boolean } + ) => void; readFile: (fname: string, options?: { encoding?: string }) => Uint8Array; mount(fs: object, options: { info?: any }, path: string): void; createNode( diff --git a/src/workerd/io/compatibility-date.capnp b/src/workerd/io/compatibility-date.capnp index 98dfaa3901c..5bf8242fb33 100644 --- a/src/workerd/io/compatibility-date.capnp +++ b/src/workerd/io/compatibility-date.capnp @@ -1191,7 +1191,7 @@ struct CompatibilityFlags @0x8f8c1b68151b6cef { pythonExternalSDK @140 :Bool $compatEnableFlag("enable_python_external_sdk") $compatDisableFlag("disable_python_external_sdk") - $experimental; + $compatEnableDate("2026-04-21"); # Don't include the Python sdk from the runtime, use a vendored copy. fastJsgStruct @141 :Bool diff --git a/src/workerd/server/tests/python/vendor_pkg_tests/BUILD b/src/workerd/server/tests/python/vendor_pkg_tests/BUILD index 7974f0e4536..2a2f82aaa71 100644 --- a/src/workerd/server/tests/python/vendor_pkg_tests/BUILD +++ b/src/workerd/server/tests/python/vendor_pkg_tests/BUILD @@ -9,6 +9,15 @@ vendored_py_wd_test("beautifulsoup4") vendored_py_wd_test( "python-workers-runtime-sdk", + feature_flags = ["enable_python_external_sdk"], +) + +vendored_py_wd_test( + "python-workers-runtime-sdk-override", + feature_flags = ["disable_python_external_sdk"], + main_py_file = "python-workers-runtime-sdk.py", + test_template = "python-workers-runtime-sdk_vendor.wd-test", + vendored_package_name = "python-workers-runtime-sdk", ) # vendored_py_wd_test("scipy") diff --git a/src/workerd/server/tests/python/vendor_pkg_tests/python-workers-runtime-sdk_vendor.wd-test b/src/workerd/server/tests/python/vendor_pkg_tests/python-workers-runtime-sdk_vendor.wd-test index a7fe0aed92b..28ee0ea9c64 100644 --- a/src/workerd/server/tests/python/vendor_pkg_tests/python-workers-runtime-sdk_vendor.wd-test +++ b/src/workerd/server/tests/python/vendor_pkg_tests/python-workers-runtime-sdk_vendor.wd-test @@ -8,7 +8,7 @@ const unitTests :Workerd.Config = ( (name = "main.py", pythonModule = embed "python-workers-runtime-sdk.py"), %PYTHON_VENDORED_MODULES% ], - compatibilityFlags = [%PYTHON_FEATURE_FLAGS, "enable_python_external_sdk", "disable_python_no_global_handlers"], + compatibilityFlags = [%PYTHON_FEATURE_FLAGS, "disable_python_no_global_handlers"], ) ), ],