workers-runtime-sdk 1.1.1__tar.gz → 1.1.3__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.1.1 → workers_runtime_sdk-1.1.3}/CHANGELOG.md +18 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/pyproject.toml +4 -5
- workers_runtime_sdk-1.1.3/src/_workers_sdk_entropy_import_context.pth +1 -0
- workers_runtime_sdk-1.1.3/src/_workers_sdk_entropy_import_context.py +183 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/asgi.py +4 -1
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/uv.lock +1 -1
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/.gitignore +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/README.md +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/workers/_workers.py +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.1.1 → workers_runtime_sdk-1.1.3}/src/workers/workflows.py +0 -0
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.1.3 (2026-05-04)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Add entropy import context for packages from workerd
|
|
10
|
+
([#99](https://github.com/cloudflare/workers-py/pull/99),
|
|
11
|
+
[`6e574ca`](https://github.com/cloudflare/workers-py/commit/6e574ca000776645d3cf2883e515c96f49a43c2c))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## v1.1.2 (2026-04-21)
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
- Make top level asgi import work with snapshots
|
|
19
|
+
([#93](https://github.com/cloudflare/workers-py/pull/93),
|
|
20
|
+
[`3dd4115`](https://github.com/cloudflare/workers-py/commit/3dd41151d201aca4e1b895638fd3926eb1c68756))
|
|
21
|
+
|
|
22
|
+
|
|
5
23
|
## v1.1.1 (2026-03-18)
|
|
6
24
|
|
|
7
25
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-runtime-sdk
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
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
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "workers-runtime-sdk"
|
|
7
|
-
version = "1.1.
|
|
7
|
+
version = "1.1.3"
|
|
8
8
|
description = "Python SDK for Cloudflare Workers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -68,11 +68,10 @@ warn_unreachable = true
|
|
|
68
68
|
no_implicit_optional = true
|
|
69
69
|
|
|
70
70
|
[tool.hatch.build.targets.wheel]
|
|
71
|
-
|
|
71
|
+
include = ["src/_*.py", "src/_*.pyi", "src/_*.pth", "src/workers"]
|
|
72
72
|
|
|
73
|
-
[tool.hatch.build.targets.wheel.
|
|
74
|
-
"src
|
|
75
|
-
"src/_pyodide_entrypoint_helper.pyi" = "_pyodide_entrypoint_helper.pyi"
|
|
73
|
+
[tool.hatch.build.targets.wheel.sources]
|
|
74
|
+
"src" = ""
|
|
76
75
|
|
|
77
76
|
[tool.semantic_release]
|
|
78
77
|
assets = []
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import _workers_sdk_entropy_import_context
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Top level entropy patches for packages
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
|
|
8
|
+
from _cloudflare.allow_entropy import (
|
|
9
|
+
allow_bad_entropy_calls,
|
|
10
|
+
)
|
|
11
|
+
from _cloudflare.import_patch_manager import (
|
|
12
|
+
block_calls,
|
|
13
|
+
register_after_snapshot,
|
|
14
|
+
register_before_first_request,
|
|
15
|
+
register_create_patch,
|
|
16
|
+
register_exec_patch,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class STATE:
|
|
21
|
+
imported_rust_package = False
|
|
22
|
+
numpy_random = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@register_create_patch("tiktoken._tiktoken")
|
|
26
|
+
@register_exec_patch("cryptography.exceptions")
|
|
27
|
+
@register_exec_patch("jiter")
|
|
28
|
+
@contextmanager
|
|
29
|
+
def rust_package_context(module):
|
|
30
|
+
"""Rust packages need one entropy call if they create a rust hash map at
|
|
31
|
+
init time.
|
|
32
|
+
|
|
33
|
+
For reasons I don't entirely understand, in Pyodide 0.28 only the first Rust package to be
|
|
34
|
+
imported makes the get_entropy call. See gen_rust_import_tests() which tests that importing
|
|
35
|
+
four rust packages in different permutations works correctly.
|
|
36
|
+
"""
|
|
37
|
+
if STATE.imported_rust_package:
|
|
38
|
+
yield
|
|
39
|
+
return
|
|
40
|
+
STATE.imported_rust_package = True
|
|
41
|
+
with allow_bad_entropy_calls(1):
|
|
42
|
+
yield
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@register_exec_patch("numpy.random")
|
|
46
|
+
@contextmanager
|
|
47
|
+
def numpy_random_context(numpy_random):
|
|
48
|
+
"""numpy.random doesn't call getentropy() itself, but we want to block calls
|
|
49
|
+
that might use the bad seed.
|
|
50
|
+
|
|
51
|
+
TODO: Maybe there are more calls we can whitelist?
|
|
52
|
+
TODO: Is it not enough to just block numpy.random.mtrand calls?
|
|
53
|
+
"""
|
|
54
|
+
yield
|
|
55
|
+
# Calling default_rng() with a given seed is fine, calling it without a seed
|
|
56
|
+
# will call getentropy() and fail.
|
|
57
|
+
block_calls(numpy_random, allowlist=("default_rng", "RandomState"))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@register_after_snapshot("numpy.random")
|
|
61
|
+
def numpy_random_after_snapshot(numpy_random):
|
|
62
|
+
r1 = numpy_random.random()
|
|
63
|
+
numpy_random.set_state(STATE.numpy_random)
|
|
64
|
+
r2 = numpy_random.random()
|
|
65
|
+
if r1 != r2:
|
|
66
|
+
raise RuntimeError("random seed in bad state")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@register_before_first_request("numpy.random")
|
|
70
|
+
def numpy_random_before_first_request(numpy_random):
|
|
71
|
+
numpy_random.seed()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@register_exec_patch("numpy.random.mtrand")
|
|
75
|
+
@contextmanager
|
|
76
|
+
def numpy_random_mtrand_context(module):
|
|
77
|
+
# numpy.random.mtrand calls secrets.randbits at top level to seed itself.
|
|
78
|
+
# This will fail if we don't let it through.
|
|
79
|
+
with allow_bad_entropy_calls(1):
|
|
80
|
+
yield
|
|
81
|
+
# Block calls until we get a chance to replace the bad random seed.
|
|
82
|
+
STATE.numpy_random = module.get_state()
|
|
83
|
+
block_calls(module, allowlist=("RandomState",))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@register_exec_patch("pydantic_core")
|
|
87
|
+
@contextmanager
|
|
88
|
+
def pydantic_core_context(module):
|
|
89
|
+
try:
|
|
90
|
+
# Initial import needs one entropy call to initialize
|
|
91
|
+
# std::collections::HashMap hash seed
|
|
92
|
+
with allow_bad_entropy_calls(1):
|
|
93
|
+
yield
|
|
94
|
+
finally:
|
|
95
|
+
try:
|
|
96
|
+
with allow_bad_entropy_calls(1):
|
|
97
|
+
# validate_core_schema makes an ahash::AHashMap which makes
|
|
98
|
+
# another entropy call for its hash seed. It will throw an error
|
|
99
|
+
# but only after making the needed entropy call.
|
|
100
|
+
module.validate_core_schema(None)
|
|
101
|
+
except module.SchemaError:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@register_exec_patch("aiohttp.http_websocket")
|
|
106
|
+
@contextmanager
|
|
107
|
+
def aiohttp_http_websocket_context(module):
|
|
108
|
+
import random
|
|
109
|
+
|
|
110
|
+
Random = random.Random
|
|
111
|
+
|
|
112
|
+
def patched_Random():
|
|
113
|
+
return random
|
|
114
|
+
|
|
115
|
+
random.Random = patched_Random
|
|
116
|
+
try:
|
|
117
|
+
yield
|
|
118
|
+
finally:
|
|
119
|
+
random.Random = Random
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class NoSslFinder:
|
|
123
|
+
def find_spec(self, fullname, path, target):
|
|
124
|
+
if fullname == "ssl":
|
|
125
|
+
raise ModuleNotFoundError(
|
|
126
|
+
f"No module named {fullname!r}", name=fullname
|
|
127
|
+
) from None
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@contextmanager
|
|
131
|
+
def no_ssl():
|
|
132
|
+
"""
|
|
133
|
+
Various packages will call ssl.create_default_context() at top level which uses entropy if they
|
|
134
|
+
can import ssl. By temporarily making importing ssl raise an import error, we exercise the
|
|
135
|
+
workaround code and so avoid the entropy calls. After, we put the ssl module back to the normal
|
|
136
|
+
value.
|
|
137
|
+
"""
|
|
138
|
+
try:
|
|
139
|
+
f = NoSslFinder()
|
|
140
|
+
ssl = sys.modules.pop("ssl", None)
|
|
141
|
+
sys.meta_path.insert(0, f)
|
|
142
|
+
yield
|
|
143
|
+
finally:
|
|
144
|
+
sys.meta_path.remove(f)
|
|
145
|
+
if ssl:
|
|
146
|
+
sys.modules["ssl"] = ssl
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@register_exec_patch("aiohttp.connector")
|
|
150
|
+
@contextmanager
|
|
151
|
+
def aiohttp_connector_context(module):
|
|
152
|
+
with no_ssl():
|
|
153
|
+
yield
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@register_exec_patch("requests.adapters")
|
|
157
|
+
@contextmanager
|
|
158
|
+
def requests_adapters_context(module):
|
|
159
|
+
with no_ssl():
|
|
160
|
+
yield
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@register_exec_patch("urllib3.util.ssl_")
|
|
164
|
+
@contextmanager
|
|
165
|
+
def urllib3_util_ssl__context(module):
|
|
166
|
+
with no_ssl():
|
|
167
|
+
yield
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@register_exec_patch("langsmith._internal._constants")
|
|
171
|
+
@contextmanager
|
|
172
|
+
def langsmith__internal__constants_context(module):
|
|
173
|
+
# Langsmith uses a UUID to communicate with a background thread. This obviously won't work so we
|
|
174
|
+
# might as well allow it to make a UUID.
|
|
175
|
+
with allow_bad_entropy_calls(1):
|
|
176
|
+
yield
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@register_exec_patch("langchain_openai.chat_models.base")
|
|
180
|
+
@contextmanager
|
|
181
|
+
def langchain_openai_chat_models_base_context(module):
|
|
182
|
+
with allow_bad_entropy_calls(1):
|
|
183
|
+
yield
|
|
@@ -7,7 +7,7 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
import js
|
|
9
9
|
|
|
10
|
-
from workers import Context, Request
|
|
10
|
+
from workers import Context, Request
|
|
11
11
|
|
|
12
12
|
ASGI = {"spec_version": "2.0", "version": "3.0"}
|
|
13
13
|
logger = logging.getLogger("asgi")
|
|
@@ -221,6 +221,9 @@ async def process_request(
|
|
|
221
221
|
|
|
222
222
|
# Create task to run the application in the background
|
|
223
223
|
app_task = create_proxy(create_task(run_app()))
|
|
224
|
+
|
|
225
|
+
from workers import wait_until
|
|
226
|
+
|
|
224
227
|
wait_until(app_task)
|
|
225
228
|
|
|
226
229
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|