Skip to content

Commit

Permalink
Implements the start of an SDK for Python Workers.
Browse files Browse the repository at this point in the history
  • Loading branch information
dom96 committed Oct 18, 2024
1 parent c3b0c07 commit 317295a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
62 changes: 62 additions & 0 deletions src/pyodide/internal/workers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# This module defines a Workers API for Python. It is similar to the API provided by
# JS Workers, but with changes and additions to be more idiomatic to the Python
# programming language.
from http import HTTPMethod, HTTPStatus
from typing import TypedDict, Unpack

import js

from pyodide.http import FetchResponse, pyfetch

JSBody = (
"js.Blob | js.ArrayBuffer | js.TypedArray | js.DataView | js.FormData |"
"js.ReadableStream | js.URLSearchParams"
)
Body = "str | JSBody"
Headers = dict[str, str] | list[tuple[str, str]]


class FetchKwargs(TypedDict, total=False):
headers: Headers | None
body: "Body | None"
method: HTTPMethod = HTTPMethod.GET


async def fetch(
resource: str,
**other_options: Unpack[FetchKwargs],
) -> FetchResponse:
if "method" in other_options and isinstance(other_options["method"], HTTPMethod):
other_options["method"] = other_options["method"].value
return await pyfetch(resource, **other_options)


def Response(
body: Body,
status: HTTPStatus | int = HTTPStatus.OK,
statusText="",
headers: Headers = None,
) -> js.Response:
"""
Represents the response to a request.
Based on the JS API of the same name:
https://developer.mozilla.org/en-US/docs/Web/API/Response/Response.
"""
options = {
"status": status.value if isinstance(status, HTTPStatus) else status,
}
if len(statusText) > 0:
options["statusText"] = statusText
if headers:
if isinstance(headers, list):
# We should have a list[tuple[str, str]]
options["headers"] = js.Headers.new(headers)
elif isinstance(headers, dict):
options["headers"] = js.Headers.new(headers.items())
else:
raise AssertionError(
"Response() received unexpected type for headers argument"
)

return js.Response.new(body, **options)
15 changes: 14 additions & 1 deletion src/pyodide/python-entrypoint-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ export async function setupPackages(pyodide: Pyodide): Promise<void> {
const pymajor = pyodide._module._py_version_major();
const pyminor = pyodide._module._py_version_minor();
pyodide.site_packages = `/lib/python${pymajor}.${pyminor}/site-packages`;

// Inject modules that enable JS features to be used idiomatically from Python.
pyodide.FS.mkdir(`${pyodide.site_packages}/cloudflare`);
await injectSitePackagesModule(pyodide, 'workers', 'cloudflare/workers');

// Install patches as needed
if (TRANSITIVE_REQUIREMENTS.has('aiohttp')) {
await applyPatch(pyodide, 'aiohttp');
Expand Down Expand Up @@ -142,9 +147,17 @@ function makeHandler(pyHandlerName: string): Handler {
'prep_python',
async () => await preparePython()
);
return await enterJaegerSpan('python_code', () => {

const result = await enterJaegerSpan('python_code', () => {
return mainModule[pyHandlerName].callRelaxed(...args);
});

// Support returning a pyodide.ffi.FetchResponse.
if (result.js_response !== undefined) {
return result.js_response;
} else {
return result;
}
} catch (e) {
console.warn('Error in makeHandler');
reportError(e);
Expand Down

0 comments on commit 317295a

Please sign in to comment.