workers-runtime-sdk 1.6.0__tar.gz → 1.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/CHANGELOG.md +17 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/pyproject.toml +1 -1
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_workers_sdk_entropy_import_context.py +1 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/asgi.py +79 -27
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/uv.lock +1 -1
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/.gitignore +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/AGENTS.md +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/README.md +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_workers_sdk_entropy_import_context.pth +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_workers_sdk_entropy_import_context_loader.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/_workers.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/request.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/response.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/utils.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/workers/wsgi.py +0 -0
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.6.2 (2026-07-09)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Uuid_utils is a Rust package needs rust package import context
|
|
10
|
+
([#151](https://github.com/cloudflare/workers-py/pull/151),
|
|
11
|
+
[`61e91f3`](https://github.com/cloudflare/workers-py/commit/61e91f3b3cffc26fef411c67d018b7d5728df3c4))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## v1.6.1 (2026-07-09)
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
- Improve lifespan handling in asgi.py ([#148](https://github.com/cloudflare/workers-py/pull/148),
|
|
19
|
+
[`7c9adfc`](https://github.com/cloudflare/workers-py/commit/7c9adfce6c3997f1547901755e97c685ef6e6be3))
|
|
20
|
+
|
|
21
|
+
|
|
5
22
|
## v1.6.0 (2026-07-08)
|
|
6
23
|
|
|
7
24
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-runtime-sdk
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: Python SDK for Cloudflare Workers
|
|
5
5
|
Project-URL: Homepage, https://github.com/cloudflare/workers-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/cloudflare/workers-py/issues
|
{workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_workers_sdk_entropy_import_context.py
RENAMED
|
@@ -25,6 +25,7 @@ class STATE:
|
|
|
25
25
|
@register_create_patch("tiktoken._tiktoken")
|
|
26
26
|
@register_exec_patch("cryptography.exceptions")
|
|
27
27
|
@register_exec_patch("jiter")
|
|
28
|
+
@register_exec_patch("uuid_utils._uuid_utils")
|
|
28
29
|
@contextmanager
|
|
29
30
|
def rust_package_context(module):
|
|
30
31
|
"""Rust packages need one entropy call if they create a rust hash map at
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from asyncio import Event, Future, Queue, create_task, ensure_future
|
|
2
|
+
from asyncio import Event, Future, Queue, create_task, ensure_future
|
|
3
3
|
from collections.abc import Awaitable
|
|
4
4
|
from contextlib import contextmanager
|
|
5
|
-
from inspect import isawaitable
|
|
6
5
|
from typing import Any
|
|
7
6
|
|
|
8
7
|
import js
|
|
@@ -10,6 +9,7 @@ import js
|
|
|
10
9
|
from workers import Context, Request
|
|
11
10
|
|
|
12
11
|
ASGI = {"spec_version": "2.0", "version": "3.0"}
|
|
12
|
+
NULL_BODY_STATUSES = frozenset({101, 103, 204, 205, 304})
|
|
13
13
|
logger = logging.getLogger("asgi")
|
|
14
14
|
background_tasks = set()
|
|
15
15
|
|
|
@@ -76,42 +76,86 @@ def request_to_scope(req, env, ws=False):
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
async def start_application(app):
|
|
79
|
-
|
|
79
|
+
# Drives one ASGI lifespan startup/shutdown cycle before/after serving the
|
|
80
|
+
# request. The lifespan protocol is optional, so we must tolerate apps that
|
|
81
|
+
# don't implement it and fall back to serving requests without lifespan.
|
|
82
|
+
# https://asgi.readthedocs.io/en/latest/specs/lifespan.html
|
|
83
|
+
receive_queue = Queue()
|
|
84
|
+
await receive_queue.put({"type": "lifespan.startup"})
|
|
85
|
+
|
|
86
|
+
# `startup` resolves True on `lifespan.startup.complete`, False when the app
|
|
87
|
+
# has no lifespan support, and raises on `lifespan.startup.failed`.
|
|
88
|
+
# `shutdown_complete` mirrors the shutdown phase.
|
|
89
|
+
startup = Future()
|
|
90
|
+
shutdown_complete = Future()
|
|
80
91
|
|
|
81
92
|
async def shutdown():
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
# Nothing to shut down if the app never completed a lifespan startup.
|
|
94
|
+
if startup.done() and not startup.result():
|
|
95
|
+
return
|
|
96
|
+
await receive_queue.put({"type": "lifespan.shutdown"})
|
|
97
|
+
await shutdown_complete
|
|
84
98
|
|
|
85
|
-
|
|
99
|
+
async def no_lifespan_shutdown():
|
|
100
|
+
return
|
|
86
101
|
|
|
87
102
|
async def receive():
|
|
88
|
-
|
|
89
|
-
if isawaitable(res):
|
|
90
|
-
await res
|
|
91
|
-
return res
|
|
92
|
-
|
|
93
|
-
ready = Future()
|
|
103
|
+
return await receive_queue.get()
|
|
94
104
|
|
|
95
105
|
async def send(got):
|
|
96
106
|
if got["type"] == "lifespan.startup.complete":
|
|
97
|
-
|
|
107
|
+
if not startup.done():
|
|
108
|
+
startup.set_result(True)
|
|
109
|
+
return
|
|
110
|
+
if got["type"] == "lifespan.startup.failed":
|
|
111
|
+
message = got.get("message", "ASGI lifespan startup failed")
|
|
112
|
+
if not startup.done():
|
|
113
|
+
startup.set_exception(RuntimeError(message))
|
|
98
114
|
return
|
|
99
115
|
if got["type"] == "lifespan.shutdown.complete":
|
|
116
|
+
if not shutdown_complete.done():
|
|
117
|
+
shutdown_complete.set_result(None)
|
|
118
|
+
return
|
|
119
|
+
if got["type"] == "lifespan.shutdown.failed":
|
|
120
|
+
message = got.get("message", "ASGI lifespan shutdown failed")
|
|
121
|
+
if not shutdown_complete.done():
|
|
122
|
+
shutdown_complete.set_exception(RuntimeError(message))
|
|
100
123
|
return
|
|
101
124
|
raise RuntimeError(f"Unexpected lifespan event {got['type']}")
|
|
102
125
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
async def run_lifespan():
|
|
127
|
+
try:
|
|
128
|
+
await app(
|
|
129
|
+
{
|
|
130
|
+
"asgi": ASGI,
|
|
131
|
+
"state": {},
|
|
132
|
+
"type": "lifespan",
|
|
133
|
+
},
|
|
134
|
+
receive,
|
|
135
|
+
send,
|
|
136
|
+
)
|
|
137
|
+
# App returned without acking: a missing startup ack means it has no
|
|
138
|
+
# lifespan handler, so mark startup unsupported rather than hanging.
|
|
139
|
+
if not startup.done():
|
|
140
|
+
startup.set_result(False)
|
|
141
|
+
elif not shutdown_complete.done():
|
|
142
|
+
shutdown_complete.set_result(None)
|
|
143
|
+
except Exception as exc:
|
|
144
|
+
# Spec: an exception raised before startup is acked signals that the
|
|
145
|
+
# app doesn't support lifespan; swallow it and serve requests anyway.
|
|
146
|
+
if not startup.done():
|
|
147
|
+
startup.set_result(False)
|
|
148
|
+
return
|
|
149
|
+
# After a successful startup, a shutdown-phase error can't affect the
|
|
150
|
+
# already-served request, so log it and let shutdown complete.
|
|
151
|
+
logger.exception("Exception in ASGI lifespan application", exc_info=exc)
|
|
152
|
+
if not shutdown_complete.done():
|
|
153
|
+
shutdown_complete.set_result(None)
|
|
154
|
+
|
|
155
|
+
run_in_background(run_lifespan())
|
|
156
|
+
supported = await startup
|
|
157
|
+
if not supported:
|
|
158
|
+
return no_lifespan_shutdown
|
|
115
159
|
return shutdown
|
|
116
160
|
|
|
117
161
|
|
|
@@ -163,10 +207,10 @@ async def process_request(
|
|
|
163
207
|
if got["type"] == "http.response.start":
|
|
164
208
|
status = got["status"]
|
|
165
209
|
# Like above, we need to convert byte-pairs into string explicitly.
|
|
166
|
-
headers = [(k.decode(), v.decode()) for k, v in got
|
|
210
|
+
headers = [(k.decode(), v.decode()) for k, v in got.get("headers", [])]
|
|
167
211
|
|
|
168
212
|
elif got["type"] == "http.response.body":
|
|
169
|
-
body = got
|
|
213
|
+
body = got.get("body", b"")
|
|
170
214
|
more_body = got.get("more_body", False)
|
|
171
215
|
|
|
172
216
|
if writer is not None:
|
|
@@ -189,6 +233,14 @@ async def process_request(
|
|
|
189
233
|
result.set_result(resp)
|
|
190
234
|
with acquire_js_buffer(body) as jsbytes:
|
|
191
235
|
await writer.write(jsbytes.slice())
|
|
236
|
+
elif status in NULL_BODY_STATUSES:
|
|
237
|
+
# 101/103/204/205/304 must not carry a body per the Fetch spec.
|
|
238
|
+
# https://fetch.spec.whatwg.org/#null-body-status
|
|
239
|
+
resp = Response.new(
|
|
240
|
+
None, headers=Object.fromEntries(headers), status=status
|
|
241
|
+
)
|
|
242
|
+
result.set_result(resp)
|
|
243
|
+
finished_response.set()
|
|
192
244
|
else:
|
|
193
245
|
# Complete body in a single chunk
|
|
194
246
|
px = create_proxy(body)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workers_runtime_sdk-1.6.0 → workers_runtime_sdk-1.6.2}/src/_workers_sdk_entropy_import_context.pth
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|