workers-runtime-sdk 1.3.0__tar.gz → 1.4.0__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.
Files changed (17) hide show
  1. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/CHANGELOG.md +13 -0
  2. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/PKG-INFO +1 -1
  3. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/pyproject.toml +1 -1
  4. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/workers/_workers.py +44 -14
  5. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/.gitignore +0 -0
  6. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/AGENTS.md +0 -0
  7. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/README.md +0 -0
  8. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/_cloudflare_compat_flags.pyi +0 -0
  9. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/_pyodide_entrypoint_helper.pyi +0 -0
  10. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/_workers_sdk_entropy_import_context.pth +0 -0
  11. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/_workers_sdk_entropy_import_context.py +0 -0
  12. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/_workers_sdk_entropy_import_context_loader.py +0 -0
  13. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/asgi.py +0 -0
  14. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/workers/__init__.py +0 -0
  15. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/workers/py.typed +0 -0
  16. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/src/workers/workflows.py +0 -0
  17. {workers_runtime_sdk-1.3.0 → workers_runtime_sdk-1.4.0}/uv.lock +0 -0
@@ -2,6 +2,19 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.4.0 (2026-06-17)
6
+
7
+ ### Features
8
+
9
+ - Auto-convert Python objects that are passed to/from Queue
10
+ ([#123](https://github.com/cloudflare/workers-py/pull/123),
11
+ [`906a10a`](https://github.com/cloudflare/workers-py/commit/906a10a7392f9d823a1b6bba044300ece8763401))
12
+
13
+ - Auto-convert Python objects that are passed to/from Queue Binding
14
+ ([#123](https://github.com/cloudflare/workers-py/pull/123),
15
+ [`906a10a`](https://github.com/cloudflare/workers-py/commit/906a10a7392f9d823a1b6bba044300ece8763401))
16
+
17
+
5
18
  ## v1.3.0 (2026-06-15)
6
19
 
7
20
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workers-runtime-sdk
3
- Version: 1.3.0
3
+ Version: 1.4.0
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.3.0"
7
+ version = "1.4.0"
8
8
  description = "Python SDK for Cloudflare Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -319,8 +319,13 @@ def _manage_pyproxies():
319
319
  destroy_proxies(proxies)
320
320
 
321
321
 
322
- def _is_js_instance(val, js_cls_name):
323
- return hasattr(val, "constructor") and val.constructor.name == js_cls_name
322
+ def _is_js_instance(val, js_cls_names: str | set[str]):
323
+ if not hasattr(val, "constructor"):
324
+ return False
325
+ name = val.constructor.name
326
+ if isinstance(js_cls_names, set):
327
+ return name in js_cls_names
328
+ return name == js_cls_names
324
329
 
325
330
 
326
331
  try:
@@ -1107,13 +1112,20 @@ class _BindingWrapper:
1107
1112
 
1108
1113
  def _convert_result(self, result):
1109
1114
  converted = python_from_rpc(result)
1115
+
1116
+ # After python_from_rpc, some objects may still be JsProxy objects.
1117
+ # For now, we wrap all of them with the _BindingWrapper (or a subclass of it)
1118
+ # so that accessing attributes on them will be properly converted.
1119
+
1120
+ # TODO: This is a bit of a hack. We should revisit when there are more
1121
+ # bindings to support with different return types.
1110
1122
  if isinstance(converted, JsProxy):
1111
- # If the RPC result is another JsProxy, we assume that
1112
- # it is another RPC-wrapped object and wrap it as well.
1113
- # for example, d1.bind() returns the same object as a result.
1114
- # TODO: This is a bit of a hack. We should revisit when there are more
1115
- # bindings to support with different patterns.
1116
1123
  return self.__class__(converted)
1124
+ if isinstance(converted, list):
1125
+ return [
1126
+ self.__class__(item) if isinstance(item, JsProxy) else item
1127
+ for item in converted
1128
+ ]
1117
1129
  return converted
1118
1130
 
1119
1131
  def _getattr_helper(self, name):
@@ -1252,6 +1264,13 @@ class _WorkflowBindingWrapper:
1252
1264
 
1253
1265
 
1254
1266
  class _EnvWrapper:
1267
+ _BINDING_TYPES = {
1268
+ "KvNamespace",
1269
+ "R2Bucket",
1270
+ "D1Database",
1271
+ "WorkerQueue",
1272
+ }
1273
+
1255
1274
  def __init__(self, env: Any):
1256
1275
  self._env = env
1257
1276
 
@@ -1266,13 +1285,7 @@ class _EnvWrapper:
1266
1285
  if _is_js_instance(binding, "WorkflowImpl"):
1267
1286
  return _WorkflowBindingWrapper(binding)
1268
1287
 
1269
- if _is_js_instance(binding, "KvNamespace"):
1270
- return _BindingWrapper(binding)
1271
-
1272
- if _is_js_instance(binding, "R2Bucket"):
1273
- return _BindingWrapper(binding)
1274
-
1275
- if _is_js_instance(binding, "D1Database"):
1288
+ if _is_js_instance(binding, self._BINDING_TYPES):
1276
1289
  return _BindingWrapper(binding)
1277
1290
 
1278
1291
  return binding
@@ -1550,6 +1563,7 @@ class WorkerEntrypoint:
1550
1563
 
1551
1564
  def __init_subclass__(cls, **_kwargs: Any):
1552
1565
  _wrap_subclass(cls)
1566
+ _wrap_queue_handler(cls)
1553
1567
 
1554
1568
 
1555
1569
  class WorkflowEntrypoint:
@@ -1567,3 +1581,19 @@ class WorkflowEntrypoint:
1567
1581
  def __init_subclass__(cls, **_kwargs: Any):
1568
1582
  _wrap_subclass(cls)
1569
1583
  _wrap_workflow_step(cls)
1584
+
1585
+
1586
+ def _wrap_queue_handler(cls):
1587
+ queue_fn = getattr(cls, "queue", None)
1588
+ if queue_fn is None:
1589
+ return
1590
+
1591
+ @functools.wraps(queue_fn)
1592
+ async def wrapped_queue(self, batch, *args, **kwargs):
1593
+ wrapped_batch = _BindingWrapper(batch)
1594
+ result = queue_fn(self, wrapped_batch, *args, **kwargs)
1595
+ if inspect.iscoroutine(result):
1596
+ result = await result
1597
+ return result
1598
+
1599
+ cls.queue = wrapped_queue