Cloudflare Python Worker SDK
This SDK injects a workers module while componentizing a Cloudflare-style
Python Worker into a verglas:do-worker@0.1.0 component. A project imports the
same names as Cloudflare's Python Workers runtime; it does not import a
Verglas-specific module.
The public shape follows Cloudflare's Python Workers documentation:
from workers import DurableObject, Response, WorkerEntrypoint
class Counter(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)
class Default(WorkerEntrypoint):
async def fetch(self, request):
return Response("hello")
The module-level Cloudflare form is also accepted:
from workers import Response
async def on_fetch(request, env):
return Response("hello")
Toolchain and build
Install the published package in a virtual environment:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install verglas-worker
componentize-py --version
# componentize-py 0.25.0
Build one Wrangler project with:
verglas-worker-py-build <project-dir> --out <output-dir> [--gateway <gateway.json>]
The builder invokes componentize-py against the packaged service WIT world.
It injects workers._component, imports the
project's main module, and exports both the Worker fetch surface and the
Durable Object handler surface. The output directory receives
<sha256-of-bytes>.wasm and manifest.out.json; its nested
artifacts.worker descriptor (and artifacts.durable_object when Durable
Objects are declared) names the exact digest and output directory. An existing
gateway.json must already use those nested descriptors, which the builder
updates with the exact SHA-256 bytes. Retired top-level component_digest and
component_dir fields are rejected.
The accepted Wrangler JSON/JSONC subset is:
nameandmain;compatibility_dateandcompatibility_flags;durable_objects.bindingswithnameandclass_name;migrationsentries withtagand optionalnew_sqlite_classesornew_classes;vars;pipelinesentries with exactlybindingandstream.
Unknown keys are hard errors, including unknown nested migration keys and pipeline entries. Other Cloudflare bindings are not silently ignored; they are outside this milestone.
Cloudflare Python surface
Default(WorkerEntrypoint) is instantiated for Worker-tier requests. The
alternative on_fetch(request, env) or on_fetch(request, env, ctx) function
is dispatched directly. Durable Object classes extend DurableObject and are
constructed with (ctx, env) from the declared Wrangler binding.
The binding object uses the Python spelling id_from_name(name), get(id), and
stub.fetch(request). id_from_name computes lowercase hex(sha256(name))
locally and retains the original name for the flattened bindings.do-fetch
host call. get_by_name(name) is provided as the Python spelling of the same
named-stub operation for projects that use that Cloudflare helper.
Pipeline Stream bindings
The manifest form follows Cloudflare's current Stream binding configuration:
"pipelines": [
{ "binding": "STREAM", "stream": "stream-id" }
]
The current Cloudflare Stream page documents send(records) but does not
specify a Python-specific binding class or alternate casing. This SDK therefore
exposes the same operation as an asynchronous env.STREAM.send(records) and
uses PipelineBinding for the concrete runtime object. The binding is separate
from Durable Object namespaces and has no namespace methods.
send requires a Python list of strict JSON values, encodes the compact array as
UTF-8, and accepts an encoded body of exactly 5 MiB (5 * 1024 * 1024 bytes).
It calls the WIT bindings.do-fetch capability with the binding name, stream ID,
POST https://verglas.internal/stream/append, and
content-type: application/json. Only a 2xx response resolves. Host failures
and non-2xx responses propagate, with no HTTP or other fallback path.
Request exposes method, url, case-insensitive headers, and a byte body;
await request.text(), await request.bytes(), and await request.json()
consume the body. Response accepts text or bytes and supports
Response.json(value, status=...). The response web_socket option is paired
with ctx.accept_websocket(server) and becomes WIT accept-ws.
ctx.storage.get, put, delete, and list are asynchronous as in the
Cloudflare Python API. get/delete accept a key list and put accepts a
mapping as well as the single-key form. list returns a deterministic mapping
of keys to values.
ctx.storage.sql.exec(statement, *bindings) is synchronous and returns a
cursor with one(), to_array(), iteration, and raw(); rows support both
mapping and attribute access, following Cloudflare's SQLite storage API.
set_alarm, get_alarm, and delete_alarm use Python snake case. ctx.get_websockets()
returns attached WebSocket objects, and webSocketMessage/webSocketClose
retain Cloudflare's documented handler casing. accept_websocket is snake case
because the Python documentation exposes the state API through the Python
runtime's idiomatic layer; its wire result is the exact accept-ws field from
the WebSocket hibernation API.
Deterministic storage encoding
The WIT storage import carries bytes, while Cloudflare Durable Object storage uses JavaScript structured clone. This implementation uses canonical UTF-8 JSON with tagged values:
None, booleans, integers, finite floats, strings, bytes, lists/tuples, and string-keyed dictionaries are supported;- dictionary keys are sorted, integers and floats use canonical text, and bytes use base64;
- non-finite floats, non-string object keys, JavaScript
undefined,Date,Map, object identity graphs, and other JavaScript-only values fail loudly.
This is a deliberate Divergence from Cloudflare's exact structured-clone value model. It is deterministic and preserves the Python values used by the supported examples; it is not presented as a byte-for-byte Cloudflare encoding. WebSocket attachments use the same tagged encoding and remain bounded to 16 KiB.
The v0 ctx.wait_until implementation awaits queued work before event completion,
which is the documented compatibility-page divergence. SQL parameter bindings
are converted to SQLite literals before the one-string sql-rows import because
WIT v2 does not yet carry a parameter list; unsupported binding types fail rather
than being stringified.
Verification
python3 -m unittest discover -s packages/worker-py/tests -v
verglas-worker-py-build examples/do-workers/py-counter --out /tmp/py-counter-build
wasm-tools component wit /tmp/py-counter-build/<digest>.wasm | tail -80
wasm-tools validate /tmp/py-counter-build/<digest>.wasm
wc -c /tmp/py-counter-build/<digest>.wasm
The artifact must expose worker, handler, and imports for storage,
sockets, and bindings; its digest filename and manifest digest must equal
the SHA-256 of the emitted bytes.
Metadata
Release files for verglas-worker 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| verglas_worker-0.1.0.tar.gz | 37.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| verglas_worker-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 67.7 kB
Release files / verglas_worker-0.1.0.tar.gz
| Download URL | verglas_worker-0.1.0.tar.gz |
|---|---|
| Size | 37.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa12b21ac37380fc4830b129c7afdd3d27a3d806284a84f2d56b98a57b69a701
|
|
BLAKE2b-256 checksum How to use checksums |
8191bc8719272619349eef4109fb82e1b7bd3e63f18ca7dc28081925b7a03db1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / verglas_worker-0.1.0-py3-none-any.whl
| Download URL | verglas_worker-0.1.0-py3-none-any.whl |
|---|---|
| Size | 30.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6a9ba5e54035d3a2a688af23b5f768a7c05adb83783d3b0fecd5880552a4df2
|
|
BLAKE2b-256 checksum How to use checksums |
1c3d6040223c5a59ee4cab68706de909b712d4172d9c850c58ee4282335d3a5e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log