workers-runtime-sdk 1.6.11__tar.gz → 1.6.12__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 (167) hide show
  1. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/CHANGELOG.md +9 -0
  2. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/PKG-INFO +2 -2
  3. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/pyproject.toml +1 -1
  4. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/asgi.py +2 -2
  5. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +27 -0
  6. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi-ws-disconnect/worker.py +23 -1
  7. workers_runtime_sdk-1.6.12/tests/workerd-test/wsgi/pyproject.toml +5 -0
  8. workers_runtime_sdk-1.6.12/tests/workerd-test/wsgi/tests/test_wsgi.py +105 -0
  9. workers_runtime_sdk-1.6.12/tests/workerd-test/wsgi/worker.py +131 -0
  10. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/wsgi/wsgi.wd-test +4 -0
  11. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/uv.lock +1 -1
  12. workers_runtime_sdk-1.6.11/tests/workerd-test/wsgi/pyproject.toml +0 -5
  13. workers_runtime_sdk-1.6.11/tests/workerd-test/wsgi/worker.py +0 -205
  14. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/.gitignore +0 -0
  15. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/AGENTS.md +0 -0
  16. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/README.md +0 -0
  17. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_cloudflare_compat_flags.pyi +0 -0
  18. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_pyodide_entrypoint_helper.pyi +0 -0
  19. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_workers_sdk_entropy_import_context.py +0 -0
  20. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_workers_sdk_package_patches.py +0 -0
  21. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_workers_sdk_patch_loader.pth +0 -0
  22. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/_workers_sdk_patch_loader.py +0 -0
  23. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/__init__.py +0 -0
  24. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/blob.py +0 -0
  25. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/entrypoints.py +0 -0
  26. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/fetch.py +0 -0
  27. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/formdata.py +0 -0
  28. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/py.typed +0 -0
  29. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/request.py +0 -0
  30. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/response.py +0 -0
  31. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/rpc.py +0 -0
  32. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/types.py +0 -0
  33. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/utils.py +0 -0
  34. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/workflows.py +0 -0
  35. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/src/workers/wsgi.py +0 -0
  36. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/public/data.json +0 -0
  37. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/public/hello.txt +0 -0
  38. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/pyproject.toml +0 -0
  39. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/conftest.py +0 -0
  40. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_analytics_engine.py +0 -0
  41. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_assets.py +0 -0
  42. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_d1.py +0 -0
  43. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_do.py +0 -0
  44. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_images.py +0 -0
  45. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_kv.py +0 -0
  46. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_mtls.py +0 -0
  47. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_queue.py +0 -0
  48. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_r2.py +0 -0
  49. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_ratelimit.py +0 -0
  50. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_vectorize.py +0 -0
  51. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_version_metadata.py +0 -0
  52. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/test_workflow.py +0 -0
  53. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/worker.py +0 -0
  54. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/worker_durable_object.py +0 -0
  55. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/src/worker_workflow.py +0 -0
  56. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/bindings-test/wrangler.jsonc +0 -0
  57. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/conftest.py +0 -0
  58. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/test_bindings.py +0 -0
  59. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/test_fastapi.py +0 -0
  60. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/test_in_workerd.py +0 -0
  61. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/test_web_frameworks.py +0 -0
  62. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
  63. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
  64. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
  65. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
  66. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
  67. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
  68. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
  69. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
  70. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
  71. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
  72. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
  73. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
  74. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
  75. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
  76. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
  77. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
  78. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
  79. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
  80. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
  81. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
  82. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
  83. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
  84. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
  85. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
  86. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
  87. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
  88. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
  89. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
  90. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
  91. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
  92. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
  93. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
  94. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
  95. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
  96. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
  97. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
  98. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
  99. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
  100. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
  101. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
  102. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
  103. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
  104. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
  105. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
  106. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
  107. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
  108. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
  109. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
  110. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
  111. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
  112. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
  113. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
  114. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
  115. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
  116. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
  117. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
  118. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
  119. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/src/worker.py +0 -0
  120. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
  121. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi/asgi.wd-test +0 -0
  122. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi/pyproject.toml +0 -0
  123. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi/tests/test_asgi.py +0 -0
  124. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi/worker.py +0 -0
  125. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
  126. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
  127. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
  128. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
  129. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
  130. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object/pyproject.toml +0 -0
  131. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object/worker.py +0 -0
  132. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
  133. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
  134. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
  135. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-abort/worker.py +0 -0
  136. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
  137. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
  138. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
  139. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
  140. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
  141. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
  142. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
  143. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
  144. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
  145. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
  146. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
  147. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/pyproject.toml +0 -0
  148. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
  149. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
  150. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
  151. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
  152. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
  153. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
  154. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/worker.py +0 -0
  155. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
  156. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
  157. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
  158. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/python-rpc/worker.js +0 -0
  159. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/python-rpc/worker.py +0 -0
  160. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
  161. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/pyproject.toml +0 -0
  162. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/sdk.wd-test +0 -0
  163. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/server.py +0 -0
  164. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
  165. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/worker.py +0 -0
  166. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
  167. {workers_runtime_sdk-1.6.11 → workers_runtime_sdk-1.6.12}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
@@ -2,6 +2,15 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.6.12 (2026-08-11)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **runtime-sdk**: Send empty WebSocket frames instead of dropping them
10
+ ([#165](https://github.com/cloudflare/workers-py/pull/165),
11
+ [`a4128ce`](https://github.com/cloudflare/workers-py/commit/a4128cee402aa6f28f01e3e2268241d05d9fd393))
12
+
13
+
5
14
  ## v1.6.11 (2026-08-10)
6
15
 
7
16
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: workers-runtime-sdk
3
- Version: 1.6.11
3
+ Version: 1.6.12
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.6.11"
7
+ version = "1.6.12"
8
8
  description = "Python SDK for Cloudflare Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -352,12 +352,12 @@ async def process_websocket(app: Any, req: "Request | js.Request") -> js.Respons
352
352
  if got["type"] == "websocket.send":
353
353
  b = got.get("bytes", None)
354
354
  s = got.get("text", None)
355
- if b:
355
+ if b is not None:
356
356
  with acquire_js_buffer(b) as jsbytes:
357
357
  # Unlike the `Response` constructor, server.send seems to
358
358
  # eagerly copy the source buffer
359
359
  server.send(jsbytes)
360
- if s:
360
+ if s is not None:
361
361
  server.send(s)
362
362
 
363
363
  else:
@@ -26,6 +26,22 @@ def _listen(ws, event_type):
26
26
  return fut
27
27
 
28
28
 
29
+ def _collect(ws, count):
30
+ """Future resolved with the payloads of the first `count` messages."""
31
+ fut = asyncio.get_event_loop().create_future()
32
+ messages = []
33
+
34
+ def callback(evt):
35
+ messages.append(evt.data)
36
+ if len(messages) == count and not fut.done():
37
+ fut.set_result(messages)
38
+
39
+ proxy = create_proxy(callback)
40
+ _proxies.append(proxy)
41
+ ws.addEventListener("message", proxy)
42
+ return fut
43
+
44
+
29
45
  async def _ws_connect(path):
30
46
  # Upgrade through the raw JS binding (as durable-object-websocket's
31
47
  # tester.js does): the SDK fetch wrapper routes through pyfetch, whose
@@ -113,3 +129,14 @@ async def test_binary_frame_arrives_as_asgi_bytes():
113
129
  data = evt.data
114
130
  assert not isinstance(data, str), f"delivered to the app as text: {data!r}"
115
131
  assert data.to_bytes() == b"bytes=" + payload
132
+
133
+
134
+ @pytest.mark.asyncio
135
+ async def test_empty_frames_reach_the_client():
136
+ async with _ws_session("/ws-empty") as ws:
137
+ received = _collect(ws, 3)
138
+ ws.send("go")
139
+ messages = await asyncio.wait_for(received, TIMEOUT_S)
140
+ assert messages[0] == ""
141
+ assert messages[1].to_bytes() == b""
142
+ assert messages[2] == "done"
@@ -80,15 +80,37 @@ class WSEchoApp:
80
80
  await send({"type": "websocket.send", "text": reply})
81
81
 
82
82
 
83
+ class WSEmptyFrameApp:
84
+ """On each client frame, replies with an empty text frame, an empty binary
85
+ frame, and a sentinel, so a test can tell whether empty frames reach the
86
+ client at all."""
87
+
88
+ async def __call__(self, scope, receive, send):
89
+ if scope["type"] == "lifespan":
90
+ await _drain_lifespan(receive, send)
91
+ return
92
+ message = await receive()
93
+ assert message["type"] == "websocket.connect"
94
+ await send({"type": "websocket.accept"})
95
+ while True:
96
+ message = await receive()
97
+ if message["type"] == "websocket.disconnect":
98
+ return
99
+ await send({"type": "websocket.send", "text": ""})
100
+ await send({"type": "websocket.send", "bytes": b""})
101
+ await send({"type": "websocket.send", "text": "done"})
102
+
103
+
83
104
  ws_app = WSWatchApp()
84
105
  echo_app = WSEchoApp()
106
+ empty_frame_app = WSEmptyFrameApp()
85
107
 
86
108
 
87
109
  class Default(WorkerEntrypoint):
88
110
  async def fetch(self, request):
89
111
  if (request.headers.get("upgrade") or "").lower() == "websocket":
90
112
  path = urlsplit(request.url).path
91
- app = echo_app if path == "/ws-echo" else ws_app
113
+ app = {"/ws-echo": echo_app, "/ws-empty": empty_frame_app}.get(path, ws_app)
92
114
  return await asgi.websocket(app, request)
93
115
  import json
94
116
 
@@ -0,0 +1,5 @@
1
+ [project]
2
+ name = "test"
3
+ version = "0.0.0"
4
+ requires-python = ">=3.12"
5
+ dependencies = ["pytest", "pytest-asyncio<1.2.0"]
@@ -0,0 +1,105 @@
1
+ import json
2
+
3
+ import js
4
+ import pytest
5
+ from pyodide.ffi import to_js
6
+ from worker import (
7
+ STREAMING_CHUNK_SIZE,
8
+ STREAMING_NUM_CHUNKS,
9
+ crash_app,
10
+ example_hdr,
11
+ )
12
+
13
+ from workers import Request, env, wsgi
14
+
15
+
16
+ @pytest.mark.asyncio
17
+ async def test_headers():
18
+ response = await env.SELF.fetch("http://example.com/", headers=to_js(example_hdr))
19
+ assert response.status == 200
20
+ text = await response.text()
21
+ assert text == "Hello, World"
22
+ # Echoed-back headers should be present.
23
+ assert response.headers.get("header1") == "Value1"
24
+ assert response.headers.get("header2") == "Value2"
25
+
26
+
27
+ @pytest.mark.asyncio
28
+ async def test_echo_body():
29
+ response = await env.SELF.fetch(
30
+ "http://example.com/echo-body",
31
+ method="POST",
32
+ body="hello body",
33
+ )
34
+ assert response.status == 200
35
+ text = await response.text()
36
+ assert text == "hello body"
37
+
38
+
39
+ @pytest.mark.asyncio
40
+ async def test_meta():
41
+ response = await env.SELF.fetch("http://example.com/meta?foo=bar&baz=qux")
42
+ assert response.status == 200
43
+
44
+ payload = json.loads(await response.text())
45
+ assert payload["method"] == "GET"
46
+ assert payload["path"] == "/meta"
47
+ assert payload["query"] == "foo=bar&baz=qux"
48
+ assert payload["scheme"] == "http"
49
+ assert payload["has_env"] is True
50
+
51
+
52
+ @pytest.mark.asyncio
53
+ async def test_cookies():
54
+ response = await env.SELF.fetch("http://example.com/cookies")
55
+ assert response.status == 200
56
+ # `env.SELF.fetch` returns the SDK `FetchResponse`, whose `.headers` is an
57
+ # `http.client.HTTPMessage`. Repeated Set-Cookie headers are preserved as
58
+ # separate entries (see `python_request_headers_preserve_commas`), so use
59
+ # `get_all` to recover the individual values.
60
+ cookies = response.headers.get_all("Set-Cookie")
61
+ assert "a=1" in cookies
62
+ assert "b=2" in cookies
63
+
64
+
65
+ @pytest.mark.asyncio
66
+ async def test_streaming():
67
+ response = await env.SELF.fetch("http://example.com/stream")
68
+ assert response.status == 200
69
+ assert response.headers.get("content-type") == "application/octet-stream"
70
+
71
+ reader = response.body.getReader()
72
+ body_bytes = b""
73
+ while True:
74
+ result = await reader.read()
75
+ if result.done:
76
+ break
77
+ body_bytes += result.value.to_bytes()
78
+
79
+ expected_size = STREAMING_CHUNK_SIZE * STREAMING_NUM_CHUNKS
80
+ assert len(body_bytes) == expected_size, (
81
+ f"Expected {expected_size} bytes, got {len(body_bytes)}"
82
+ )
83
+ for i in range(STREAMING_NUM_CHUNKS):
84
+ start = i * STREAMING_CHUNK_SIZE
85
+ end = start + STREAMING_CHUNK_SIZE
86
+ expected_byte = i % 256
87
+ assert all(b == expected_byte for b in body_bytes[start:end])
88
+
89
+
90
+ @pytest.mark.asyncio
91
+ async def test_app_exception_is_raised():
92
+ req = js.Request.new("http://example.com/crash-test")
93
+ with pytest.raises(RuntimeError, match="app crash before response for testing"):
94
+ await wsgi.fetch(crash_app, req, env)
95
+
96
+
97
+ def test_build_environ_handles_js_and_python_requests():
98
+ # Verify `build_environ` handles JS-style and Python-style headers
99
+ # identically, mirroring the asgi `request_to_scope` check.
100
+ js_request = js.Request.new("http://example.com/", headers=to_js(example_hdr))
101
+ py_request = Request("http://example.com/", headers=example_hdr)
102
+ js_env = wsgi.build_environ(js_request, env, b"")
103
+ py_env = wsgi.build_environ(py_request, env, b"")
104
+ assert js_env["HTTP_HEADER1"] == py_env["HTTP_HEADER1"] == "Value1"
105
+ assert js_env["HTTP_HEADER2"] == py_env["HTTP_HEADER2"] == "Value2"
@@ -0,0 +1,131 @@
1
+ import asyncio
2
+ import os
3
+ import sys
4
+
5
+ import pytest
6
+ from pyodide.webloop import WebLoop
7
+
8
+ from workers import WorkerEntrypoint, wsgi
9
+
10
+
11
+ async def noop(*args):
12
+ pass
13
+
14
+
15
+ # pytest-asyncio relies on these but in Pyodide < 0.29 WebLoop does not implement them
16
+ WebLoop.shutdown_asyncgens = noop
17
+ WebLoop.shutdown_default_executor = noop
18
+
19
+ # Pyodide 0.26.0a2's _cancel_all_tasks calls task.exception() on pending tasks,
20
+ # which raises InvalidStateError under Pyodide's WebLoop.
21
+ # Ignore this error to prevent pytest-asyncio from crashing.
22
+ if sys.version_info < (3, 13):
23
+ asyncio.runners._cancel_all_tasks = lambda loop: None # type: ignore[attr-defined]
24
+
25
+
26
+ # ---------------------------------------------------------------------------
27
+ # WSGI apps
28
+ # ---------------------------------------------------------------------------
29
+
30
+
31
+ def header_echo_app(environ, start_response):
32
+ """WSGI app that echoes request headers back in the response body and headers."""
33
+ response_headers = [("Content-Type", "text/plain")]
34
+ # Echo each incoming header back out (HTTP_* keys).
35
+ for key, value in environ.items():
36
+ if key.startswith("HTTP_"):
37
+ name = key[len("HTTP_") :].replace("_", "-").title()
38
+ response_headers.append((name, value))
39
+
40
+ start_response("200 OK", response_headers)
41
+ return [b"Hello, World"]
42
+
43
+
44
+ def echo_body_app(environ, start_response):
45
+ """WSGI app that reads the request body and echoes it back."""
46
+ length = int(environ.get("CONTENT_LENGTH") or 0)
47
+ body = environ["wsgi.input"].read(length)
48
+ start_response(
49
+ "200 OK",
50
+ [("Content-Type", "application/octet-stream")],
51
+ )
52
+ return [body]
53
+
54
+
55
+ def echo_meta_app(environ, start_response):
56
+ """WSGI app that returns selected environ values so the test can assert on them."""
57
+ import json
58
+
59
+ payload = {
60
+ "method": environ["REQUEST_METHOD"],
61
+ "path": environ["PATH_INFO"],
62
+ "query": environ["QUERY_STRING"],
63
+ "scheme": environ["wsgi.url_scheme"],
64
+ "has_env": "workers.env" in environ,
65
+ }
66
+ body = json.dumps(payload).encode()
67
+ start_response("200 OK", [("Content-Type", "application/json")])
68
+ return [body]
69
+
70
+
71
+ def cookies_app(environ, start_response):
72
+ """WSGI app that sets multiple Set-Cookie headers (must not collapse)."""
73
+ start_response(
74
+ "200 OK",
75
+ [
76
+ ("Content-Type", "text/plain"),
77
+ ("Set-Cookie", "a=1"),
78
+ ("Set-Cookie", "b=2"),
79
+ ],
80
+ )
81
+ return [b"cookies"]
82
+
83
+
84
+ STREAMING_CHUNK_SIZE = 1024
85
+ STREAMING_NUM_CHUNKS = 5
86
+
87
+
88
+ def streaming_app(environ, start_response):
89
+ """WSGI app that returns multiple body chunks via a generator."""
90
+ start_response("200 OK", [("Content-Type", "application/octet-stream")])
91
+
92
+ def generate():
93
+ for i in range(STREAMING_NUM_CHUNKS):
94
+ yield bytes([i % 256]) * STREAMING_CHUNK_SIZE
95
+
96
+ return generate()
97
+
98
+
99
+ def crash_app(environ, start_response):
100
+ raise RuntimeError("app crash before response for testing")
101
+
102
+
103
+ example_hdr = {"Header1": "Value1", "Header2": "Value2"}
104
+
105
+
106
+ class Default(WorkerEntrypoint):
107
+ # Each path in this handler serves one of the WSGI apps above; the
108
+ # assertions live in tests/test_wsgi.py.
109
+ async def fetch(self, request):
110
+ from js import URL
111
+
112
+ url = URL.new(request.url)
113
+ path = url.pathname
114
+
115
+ if path == "/echo-body":
116
+ return await wsgi.fetch(echo_body_app, request, self.env)
117
+ elif path == "/meta":
118
+ return await wsgi.fetch(echo_meta_app, request, self.env)
119
+ elif path == "/cookies":
120
+ return await wsgi.fetch(cookies_app, request, self.env)
121
+ elif path == "/stream":
122
+ return await wsgi.fetch(streaming_app, request, self.env)
123
+
124
+ return await wsgi.fetch(header_echo_app, request, self.env)
125
+
126
+ async def test(self, ctrl):
127
+ os.chdir("/session/metadata/tests")
128
+ args = [".", "-vv"]
129
+ if self.env.color:
130
+ args.append("--color=yes")
131
+ assert pytest.main(args) == 0
@@ -10,6 +10,10 @@ const unitTests :Workerd.Config = (
10
10
  ],
11
11
  bindings = [
12
12
  ( name = "SELF", service = "python-wsgi" ),
13
+ (
14
+ name = "color",
15
+ json = "%COLOR"
16
+ ),
13
17
  ],
14
18
  compatibilityDate = "%COMPAT_DATE",
15
19
  compatibilityFlags = ["python_workers"],
@@ -345,7 +345,7 @@ wheels = [
345
345
 
346
346
  [[package]]
347
347
  name = "workers-runtime-sdk"
348
- version = "1.6.11"
348
+ version = "1.6.12"
349
349
  source = { editable = "." }
350
350
 
351
351
  [package.dev-dependencies]
@@ -1,5 +0,0 @@
1
- [project]
2
- name = "test"
3
- version = "0.0.0"
4
- requires-python = ">=3.12"
5
- dependencies = ["pytest"]
@@ -1,205 +0,0 @@
1
- import js
2
- from pyodide.ffi import to_js
3
-
4
- from workers import Request, WorkerEntrypoint, wsgi
5
-
6
- # ---------------------------------------------------------------------------
7
- # WSGI apps
8
- # ---------------------------------------------------------------------------
9
-
10
-
11
- def header_echo_app(environ, start_response):
12
- """WSGI app that echoes request headers back in the response body and headers."""
13
- response_headers = [("Content-Type", "text/plain")]
14
- # Echo each incoming header back out (HTTP_* keys).
15
- for key, value in environ.items():
16
- if key.startswith("HTTP_"):
17
- name = key[len("HTTP_") :].replace("_", "-").title()
18
- response_headers.append((name, value))
19
-
20
- start_response("200 OK", response_headers)
21
- return [b"Hello, World"]
22
-
23
-
24
- def echo_body_app(environ, start_response):
25
- """WSGI app that reads the request body and echoes it back."""
26
- length = int(environ.get("CONTENT_LENGTH") or 0)
27
- body = environ["wsgi.input"].read(length)
28
- start_response(
29
- "200 OK",
30
- [("Content-Type", "application/octet-stream")],
31
- )
32
- return [body]
33
-
34
-
35
- def echo_meta_app(environ, start_response):
36
- """WSGI app that returns selected environ values so the test can assert on them."""
37
- import json
38
-
39
- payload = {
40
- "method": environ["REQUEST_METHOD"],
41
- "path": environ["PATH_INFO"],
42
- "query": environ["QUERY_STRING"],
43
- "scheme": environ["wsgi.url_scheme"],
44
- "has_env": "workers.env" in environ,
45
- }
46
- body = json.dumps(payload).encode()
47
- start_response("200 OK", [("Content-Type", "application/json")])
48
- return [body]
49
-
50
-
51
- def cookies_app(environ, start_response):
52
- """WSGI app that sets multiple Set-Cookie headers (must not collapse)."""
53
- start_response(
54
- "200 OK",
55
- [
56
- ("Content-Type", "text/plain"),
57
- ("Set-Cookie", "a=1"),
58
- ("Set-Cookie", "b=2"),
59
- ],
60
- )
61
- return [b"cookies"]
62
-
63
-
64
- STREAMING_CHUNK_SIZE = 1024
65
- STREAMING_NUM_CHUNKS = 5
66
-
67
-
68
- def streaming_app(environ, start_response):
69
- """WSGI app that returns multiple body chunks via a generator."""
70
- start_response("200 OK", [("Content-Type", "application/octet-stream")])
71
-
72
- def generate():
73
- for i in range(STREAMING_NUM_CHUNKS):
74
- yield bytes([i % 256]) * STREAMING_CHUNK_SIZE
75
-
76
- return generate()
77
-
78
-
79
- def crash_app(environ, start_response):
80
- raise RuntimeError("app crash before response for testing")
81
-
82
-
83
- example_hdr = {"Header1": "Value1", "Header2": "Value2"}
84
-
85
-
86
- class Default(WorkerEntrypoint):
87
- async def fetch(self, request):
88
- from js import URL
89
-
90
- url = URL.new(request.url)
91
- path = url.pathname
92
-
93
- if path == "/echo-body":
94
- return await wsgi.fetch(echo_body_app, request, self.env)
95
- elif path == "/meta":
96
- return await wsgi.fetch(echo_meta_app, request, self.env)
97
- elif path == "/cookies":
98
- return await wsgi.fetch(cookies_app, request, self.env)
99
- elif path == "/stream":
100
- return await wsgi.fetch(streaming_app, request, self.env)
101
-
102
- # Verify `build_environ` handles JS-style and Python-style headers
103
- # identically, mirroring the asgi `request_to_scope` check.
104
- js_request = js.Request.new("http://example.com/", headers=to_js(example_hdr))
105
- py_request = Request("http://example.com/", headers=example_hdr)
106
- js_env = wsgi.build_environ(js_request, self.env, b"")
107
- py_env = wsgi.build_environ(py_request, self.env, b"")
108
- assert js_env["HTTP_HEADER1"] == py_env["HTTP_HEADER1"] == "Value1"
109
- assert js_env["HTTP_HEADER2"] == py_env["HTTP_HEADER2"] == "Value2"
110
-
111
- return await wsgi.fetch(header_echo_app, request, self.env)
112
-
113
- async def test(self, ctrl):
114
- await test_headers(self.env)
115
- await test_echo_body(self.env)
116
- await test_meta(self.env)
117
- await test_cookies(self.env)
118
- await test_streaming(self.env)
119
- await test_app_exception_is_raised(self.env)
120
-
121
-
122
- # ---------------------------------------------------------------------------
123
- # Tests
124
- # ---------------------------------------------------------------------------
125
-
126
-
127
- async def test_headers(env):
128
- response = await env.SELF.fetch("http://example.com/", headers=to_js(example_hdr))
129
- assert response.status == 200
130
- text = await response.text()
131
- assert text == "Hello, World"
132
- # Echoed-back headers should be present.
133
- assert response.headers.get("header1") == "Value1"
134
- assert response.headers.get("header2") == "Value2"
135
-
136
-
137
- async def test_echo_body(env):
138
- response = await env.SELF.fetch(
139
- "http://example.com/echo-body",
140
- method="POST",
141
- body="hello body",
142
- )
143
- assert response.status == 200
144
- text = await response.text()
145
- assert text == "hello body"
146
-
147
-
148
- async def test_meta(env):
149
- response = await env.SELF.fetch("http://example.com/meta?foo=bar&baz=qux")
150
- assert response.status == 200
151
- import json
152
-
153
- payload = json.loads(await response.text())
154
- assert payload["method"] == "GET"
155
- assert payload["path"] == "/meta"
156
- assert payload["query"] == "foo=bar&baz=qux"
157
- assert payload["scheme"] == "http"
158
- assert payload["has_env"] is True
159
-
160
-
161
- async def test_cookies(env):
162
- response = await env.SELF.fetch("http://example.com/cookies")
163
- assert response.status == 200
164
- # `env.SELF.fetch` returns the SDK `FetchResponse`, whose `.headers` is an
165
- # `http.client.HTTPMessage`. Repeated Set-Cookie headers are preserved as
166
- # separate entries (see `python_request_headers_preserve_commas`), so use
167
- # `get_all` to recover the individual values.
168
- cookies = response.headers.get_all("Set-Cookie")
169
- assert "a=1" in cookies
170
- assert "b=2" in cookies
171
-
172
-
173
- async def test_streaming(env):
174
- response = await env.SELF.fetch("http://example.com/stream")
175
- assert response.status == 200
176
- assert response.headers.get("content-type") == "application/octet-stream"
177
-
178
- reader = response.body.getReader()
179
- body_bytes = b""
180
- while True:
181
- result = await reader.read()
182
- if result.done:
183
- break
184
- body_bytes += result.value.to_bytes()
185
-
186
- expected_size = STREAMING_CHUNK_SIZE * STREAMING_NUM_CHUNKS
187
- assert len(body_bytes) == expected_size, (
188
- f"Expected {expected_size} bytes, got {len(body_bytes)}"
189
- )
190
- for i in range(STREAMING_NUM_CHUNKS):
191
- start = i * STREAMING_CHUNK_SIZE
192
- end = start + STREAMING_CHUNK_SIZE
193
- expected_byte = i % 256
194
- assert all(b == expected_byte for b in body_bytes[start:end])
195
-
196
-
197
- async def test_app_exception_is_raised(env):
198
- req = js.Request.new("http://example.com/crash-test")
199
- threw = False
200
- try:
201
- await wsgi.fetch(crash_app, req, env)
202
- except RuntimeError as e:
203
- threw = True
204
- assert "app crash before response for testing" in str(e)
205
- assert threw, "Expected RuntimeError to be raised from wsgi.fetch"