workers-runtime-sdk 1.8.2__tar.gz → 1.8.5__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 (198) hide show
  1. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/CHANGELOG.md +27 -0
  2. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/PKG-INFO +1 -1
  3. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/pyproject.toml +6 -30
  4. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_entropy_import_context.py +59 -0
  5. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/asgi.py +12 -3
  6. workers_runtime_sdk-1.8.5/tests/bindings-test/pyproject.toml +19 -0
  7. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_mysql.py +21 -0
  8. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_postgresql.py +65 -0
  9. workers_runtime_sdk-1.8.5/tests/bindings-test/src/worker.py +32 -0
  10. workers_runtime_sdk-1.8.5/tests/conftest.py +116 -0
  11. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/test_fastapi.py +1 -5
  12. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/test_in_workerd.py +35 -13
  13. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/pyproject.toml +4 -0
  14. workers_runtime_sdk-1.8.5/tests/web-frameworks-test/django-async/src/worker.py +104 -0
  15. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +4 -0
  16. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/worker.py +4 -73
  17. workers_runtime_sdk-1.8.5/tests/web-frameworks-test/flask-tests/pyproject.toml +8 -0
  18. workers_runtime_sdk-1.8.5/tests/web-frameworks-test/flask-tests/src/worker.py +5 -0
  19. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/tests/test_asgi.py +46 -0
  20. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +12 -17
  21. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/pyproject.toml +6 -1
  22. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -1
  23. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_litestar.py +7 -0
  24. workers_runtime_sdk-1.8.2/tests/workerd-test/entropy-patches/tests/test_rust_packages.py → workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_mcp.py +3 -3
  25. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_opentelemetry.py +8 -0
  26. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +19 -0
  27. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/worker.py +19 -0
  28. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/http-client.wd-test +45 -0
  29. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/origin.py +60 -0
  30. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/pyproject.toml +5 -0
  31. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_http_client.py +162 -0
  32. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_urllib_request.py +121 -0
  33. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/worker.py +14 -0
  34. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/wrangler.jsonc +5 -0
  35. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/uv.lock +23 -1
  36. workers_runtime_sdk-1.8.2/tests/bindings-test/pyproject.toml +0 -5
  37. workers_runtime_sdk-1.8.2/tests/bindings-test/src/worker.py +0 -186
  38. workers_runtime_sdk-1.8.2/tests/conftest.py +0 -290
  39. workers_runtime_sdk-1.8.2/tests/web-frameworks-test/django-async/src/worker.py +0 -206
  40. workers_runtime_sdk-1.8.2/tests/web-frameworks-test/flask-tests/pyproject.toml +0 -5
  41. workers_runtime_sdk-1.8.2/tests/web-frameworks-test/flask-tests/src/worker.py +0 -89
  42. workers_runtime_sdk-1.8.2/tests/workerd-test/entropy-patches/worker.py +0 -27
  43. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/.gitignore +0 -0
  44. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/AGENTS.md +0 -0
  45. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/README.md +0 -0
  46. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_cloudflare_compat_flags.pyi +0 -0
  47. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_pyodide_entrypoint_helper.pyi +0 -0
  48. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_package_patches.py +0 -0
  49. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.pth +0 -0
  50. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.py +0 -0
  51. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/asgi.py +0 -0
  52. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/__init__.py +0 -0
  53. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/blob.py +0 -0
  54. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/entrypoints.py +0 -0
  55. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/fetch.py +0 -0
  56. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/formdata.py +0 -0
  57. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/py.typed +0 -0
  58. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/request.py +0 -0
  59. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/response.py +0 -0
  60. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/rpc.py +0 -0
  61. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/types.py +0 -0
  62. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/utils.py +0 -0
  63. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/workflows.py +0 -0
  64. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/src/workers/wsgi.py +0 -0
  65. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/data.json +0 -0
  66. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/hello.txt +0 -0
  67. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/conftest.py +0 -0
  68. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_analytics_engine.py +0 -0
  69. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_assets.py +0 -0
  70. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_d1.py +0 -0
  71. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_do.py +0 -0
  72. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_images.py +0 -0
  73. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_kv.py +0 -0
  74. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_mtls.py +0 -0
  75. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_queue.py +0 -0
  76. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_r2.py +0 -0
  77. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_ratelimit.py +0 -0
  78. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_vectorize.py +0 -0
  79. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_version_metadata.py +0 -0
  80. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_workflow.py +0 -0
  81. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_durable_object.py +0 -0
  82. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_workflow.py +0 -0
  83. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/bindings-test/wrangler.jsonc +0 -0
  84. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/test_bindings.py +0 -0
  85. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/test_flask.py +0 -0
  86. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/test_web_frameworks.py +0 -0
  87. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
  88. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
  89. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
  90. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
  91. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
  92. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
  93. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
  94. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
  95. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
  96. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
  97. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
  98. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
  99. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
  100. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
  101. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
  102. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
  103. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
  104. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
  105. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
  106. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
  107. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
  108. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
  109. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
  110. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
  111. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
  112. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
  113. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
  114. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
  115. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
  116. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
  117. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
  118. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
  119. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
  120. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
  121. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
  122. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
  123. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
  124. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
  125. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
  126. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
  127. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
  128. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
  129. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
  130. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
  131. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
  132. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
  133. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
  134. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
  135. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
  136. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
  137. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
  138. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
  139. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
  140. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +0 -0
  141. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_boundaries.py +0 -0
  142. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_io.py +0 -0
  143. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +0 -0
  144. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +0 -0
  145. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +0 -0
  146. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
  147. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
  148. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +0 -0
  149. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
  150. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/src/test_response.py +0 -0
  151. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/wrangler.jsonc +0 -0
  152. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/asgi.wd-test +0 -0
  153. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/pyproject.toml +0 -0
  154. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/worker.py +0 -0
  155. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
  156. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
  157. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
  158. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
  159. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
  160. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
  161. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/pyproject.toml +0 -0
  162. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/worker.py +0 -0
  163. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
  164. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
  165. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
  166. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/worker.py +0 -0
  167. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
  168. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
  169. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
  170. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
  171. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
  172. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
  173. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
  174. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
  175. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
  176. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
  177. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
  178. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
  179. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
  180. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
  181. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
  182. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
  183. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
  184. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
  185. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.js +0 -0
  186. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.py +0 -0
  187. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
  188. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/pyproject.toml +0 -0
  189. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/sdk.wd-test +0 -0
  190. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/server.py +0 -0
  191. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
  192. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/worker.py +0 -0
  193. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
  194. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/pyproject.toml +0 -0
  195. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
  196. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/worker.py +0 -0
  197. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
  198. {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
@@ -2,6 +2,33 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.8.5 (2026-09-17)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **runtime-sdk**: Fix top-level import for opentelemetry package
10
+ ([#248](https://github.com/cloudflare/workers-py/pull/248),
11
+ [`338c12e`](https://github.com/cloudflare/workers-py/commit/338c12e5dc6aada9dd20968fdae6bb6e805ad33e))
12
+
13
+
14
+ ## v1.8.4 (2026-09-08)
15
+
16
+ ### Bug Fixes
17
+
18
+ - **runtime-sdk**: Fix top-level entropy call for litestar and fix entropy tests
19
+ ([#241](https://github.com/cloudflare/workers-py/pull/241),
20
+ [`99b77c7`](https://github.com/cloudflare/workers-py/commit/99b77c7658d1e4b0591233b8ce6cc179719751e3))
21
+
22
+
23
+ ## v1.8.3 (2026-08-31)
24
+
25
+ ### Bug Fixes
26
+
27
+ - **runtime-sdk**: Stop losing details of ASGI lifespan failures
28
+ ([#172](https://github.com/cloudflare/workers-py/pull/172),
29
+ [`c6d1f69`](https://github.com/cloudflare/workers-py/commit/c6d1f69e96fd13b5b9e41f48e70aebb7469310c8))
30
+
31
+
5
32
  ## v1.8.2 (2026-08-31)
6
33
 
7
34
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: workers-runtime-sdk
3
- Version: 1.8.2
3
+ Version: 1.8.5
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.8.2"
7
+ version = "1.8.5"
8
8
  description = "Python SDK for Cloudflare Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -21,42 +21,18 @@ dev = [
21
21
  "ruff>=0.1.0",
22
22
  "mypy>=1.0.0",
23
23
  "requests>=2.28.0",
24
+ "testlib[host]",
24
25
  ]
25
26
 
27
+ [tool.uv.sources]
28
+ testlib = { path = "../testlib", editable = true }
29
+
26
30
  [project.urls]
27
31
  "Homepage" = "https://github.com/cloudflare/workers-py"
28
32
  "Bug Tracker" = "https://github.com/cloudflare/workers-py/issues"
29
33
 
30
34
  [tool.ruff]
31
- target-version = "py311"
32
- lint.select = [
33
- "B0", # bugbear (all B0* checks enabled by default)
34
- "B904", # bugbear (Within an except clause, raise exceptions with raise ... from err)
35
- "B905", # bugbear (zip() without an explicit strict= parameter set.)
36
- "C4", # flake8-comprehensions
37
- "C9", # mccabe complexity
38
- "E", # pycodestyles
39
- "F", # pyflakes
40
- "I", # isort
41
- "PERF", # Perflint
42
- "PGH", # pygrep-hooks
43
- "PL", # Pylint
44
- "UP", # pyupgrade
45
- "W", # pycodestyles
46
- ]
47
- lint.ignore = [
48
- "C901", # Too complex
49
- "E402",
50
- "E501",
51
- "E731",
52
- "E741",
53
- "PLR0911", # Too many return statements
54
- "PLR0915", # Too many statements
55
- "PLW2901",
56
- "UP031",
57
- "UP038", # Use X | Y instead of (X, Y)
58
- ]
59
- lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments = true
35
+ extend = "../../ruff.toml"
60
36
  lint.per-file-ignores."tests/**" = ["PLR2004", "PLR0913"]
61
37
  lint.per-file-ignores."tests/workerd-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
62
38
  lint.per-file-ignores."tests/bindings-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
@@ -4,6 +4,7 @@ Top level entropy patches for packages
4
4
 
5
5
  import sys
6
6
  from contextlib import contextmanager
7
+ from importlib.metadata import PackageNotFoundError, version
7
8
 
8
9
  from _cloudflare.allow_entropy import (
9
10
  allow_bad_entropy_calls,
@@ -17,6 +18,29 @@ from _cloudflare.import_patch_manager import (
17
18
  )
18
19
 
19
20
 
21
+ @contextmanager
22
+ def allow_bad_entropy_calls_for_version(
23
+ package_name: str,
24
+ num_calls: int,
25
+ min_version: tuple[int, ...],
26
+ max_version: tuple[int, ...] | None = None,
27
+ ):
28
+ try:
29
+ package_version = tuple(map(int, version(package_name).split(".")))
30
+ except PackageNotFoundError:
31
+ yield
32
+ return
33
+
34
+ if package_version < min_version or (
35
+ max_version is not None and package_version > max_version
36
+ ):
37
+ yield
38
+ return
39
+
40
+ with allow_bad_entropy_calls(num_calls):
41
+ yield
42
+
43
+
20
44
  class STATE:
21
45
  imported_rust_package = False
22
46
  numpy_random = None
@@ -178,3 +202,38 @@ def langsmith__internal__constants_context(module):
178
202
  def langchain_openai_chat_models_base_context(module):
179
203
  with allow_bad_entropy_calls(1):
180
204
  yield
205
+
206
+
207
+ @register_exec_patch("opentelemetry.context")
208
+ @contextmanager
209
+ def opentelemetry_context(module):
210
+ # OpenTelemetry creates three UUID-backed keys.
211
+ with allow_bad_entropy_calls_for_version("opentelemetry-api", 3, (1, 40, 0)):
212
+ yield
213
+
214
+
215
+ @register_exec_patch("opentelemetry.trace.propagation")
216
+ @contextmanager
217
+ def opentelemetry_trace_propagation_context(module):
218
+ # OpenTelemetry creates a UUID-backed key.
219
+ with allow_bad_entropy_calls(1):
220
+ yield
221
+
222
+
223
+ @register_exec_patch("opentelemetry.baggage")
224
+ @contextmanager
225
+ def opentelemetry_baggage_context(module):
226
+ # OpenTelemetry creates a UUID-backed key.
227
+ with allow_bad_entropy_calls(1):
228
+ yield
229
+
230
+
231
+ @register_exec_patch("litestar.openapi.controller")
232
+ @register_exec_patch("litestar.constants")
233
+ @contextmanager
234
+ def litestar_context(module):
235
+ # Uses os.urandom() to generate a OPENAPI_JSON_HANDLER_NAME
236
+ # https://github.com/litestar-org/litestar/blob/e3b6a1d103a9160a575dce01ae34839e6e9bf990/litestar/constants.py#L19
237
+ # https://github.com/litestar-org/litestar/blob/v2.24.0/litestar/openapi/controller.py#L27
238
+ with allow_bad_entropy_calls(1):
239
+ yield
@@ -127,7 +127,9 @@ async def start_application(app):
127
127
  startup.set_result(True)
128
128
  return
129
129
  if got["type"] == "lifespan.startup.failed":
130
- message = got.get("message", "ASGI lifespan startup failed")
130
+ # `or`, not a .get default: an empty message field is legal and
131
+ # would otherwise produce RuntimeError('').
132
+ message = got.get("message") or "ASGI lifespan startup failed"
131
133
  if not startup.done():
132
134
  startup.set_exception(RuntimeError(message))
133
135
  return
@@ -136,7 +138,7 @@ async def start_application(app):
136
138
  shutdown_complete.set_result(None)
137
139
  return
138
140
  if got["type"] == "lifespan.shutdown.failed":
139
- message = got.get("message", "ASGI lifespan shutdown failed")
141
+ message = got.get("message") or "ASGI lifespan shutdown failed"
140
142
  if not shutdown_complete.done():
141
143
  shutdown_complete.set_exception(RuntimeError(message))
142
144
  return
@@ -161,8 +163,15 @@ async def start_application(app):
161
163
  shutdown_complete.set_result(None)
162
164
  except Exception as exc:
163
165
  # Spec: an exception raised before startup is acked signals that the
164
- # app doesn't support lifespan; swallow it and serve requests anyway.
166
+ # app doesn't support lifespan; serve requests anyway. Log it, or an
167
+ # app that crashed mid-startup looks like one with no lifespan
168
+ # handler at all.
165
169
  if not startup.done():
170
+ logger.debug(
171
+ "ASGI lifespan task raised before reporting startup; "
172
+ "treating the app as not supporting lifespan",
173
+ exc_info=exc,
174
+ )
166
175
  startup.set_result(False)
167
176
  return
168
177
  # After a successful startup, a shutdown-phase error can't affect the
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "bindings-test"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.12"
5
+ dependencies = [
6
+ "pytest",
7
+ "pytest-asyncio<1.2.0",
8
+ # These are for hyperdrive tests
9
+ "pg8000",
10
+ "pymysql",
11
+ "aiomysql",
12
+ "psycopg[binary]; python_version >= '3.14'",
13
+ "asyncpg; python_version >= '3.14'",
14
+ "cryptography",
15
+ "testlib",
16
+ ]
17
+
18
+ [tool.uv.sources]
19
+ testlib = { path = "../testlib/dist/testlib-0.0.0-py3-none-any.whl" }
@@ -24,6 +24,7 @@ uv run pytest tests/test_bindings.py -m hyperdrive -k mysql
24
24
 
25
25
  import sys
26
26
 
27
+ import aiomysql
27
28
  import pymysql
28
29
  import pytest
29
30
  from conftest import unique_table_name
@@ -58,6 +59,26 @@ async def test_connect(env):
58
59
  conn.close()
59
60
 
60
61
 
62
+ @pytest.mark.asyncio
63
+ async def test_connect_aiomysql(env):
64
+ hd = env.HYPERDRIVE_MYSQL
65
+ conn = await aiomysql.connect(
66
+ host=hd.host,
67
+ port=int(hd.port),
68
+ user=hd.user,
69
+ password=hd.password,
70
+ db=hd.database,
71
+ # Hyperdrive terminates TLS to the origin, so this hop is plaintext.
72
+ ssl=None,
73
+ )
74
+ try:
75
+ async with conn.cursor() as cur:
76
+ await cur.execute("SELECT %s", (1,))
77
+ assert await cur.fetchone() == (1,)
78
+ finally:
79
+ await conn.ensure_closed()
80
+
81
+
61
82
  @pytest.mark.asyncio
62
83
  async def test_create_insert_select(env):
63
84
  conn = _connect(env)
@@ -61,6 +61,71 @@ async def test_connect(env):
61
61
  conn.close()
62
62
 
63
63
 
64
+ @pytest.mark.asyncio
65
+ async def test_connect_psycopg(env):
66
+ import psycopg # noqa: PLC0415
67
+
68
+ assert psycopg.pq.__impl__ == "binary"
69
+ hd = env.HYPERDRIVE_PG
70
+ with psycopg.connect(
71
+ host=hd.host,
72
+ port=int(hd.port),
73
+ user=hd.user,
74
+ password=hd.password,
75
+ dbname=hd.database,
76
+ # Hyperdrive terminates TLS to the origin, so this hop is plaintext.
77
+ sslmode="disable",
78
+ ) as conn:
79
+ with conn.cursor() as cur:
80
+ cur.execute("SELECT %s", (1,))
81
+ assert cur.fetchone() == (1,)
82
+
83
+
84
+ @pytest.mark.asyncio
85
+ async def test_asyncpg_crud(env):
86
+ import asyncpg # noqa: PLC0415
87
+
88
+ hd = env.HYPERDRIVE_PG
89
+ conn = await asyncpg.connect(
90
+ host=hd.host,
91
+ port=int(hd.port),
92
+ user=hd.user,
93
+ password=hd.password,
94
+ database=hd.database,
95
+ # Hyperdrive terminates TLS to the origin, so this hop is plaintext.
96
+ ssl=False,
97
+ )
98
+ table = unique_table_name()
99
+ try:
100
+ await conn.execute(
101
+ f"CREATE TABLE {table} (id SERIAL PRIMARY KEY, name TEXT, value INT)"
102
+ )
103
+ await conn.execute(
104
+ f"INSERT INTO {table} (name, value) VALUES ($1, $2)", "alpha", 1
105
+ )
106
+
107
+ row = await conn.fetchrow(
108
+ f"SELECT name, value FROM {table} WHERE name = $1", "alpha"
109
+ )
110
+ assert tuple(row) == ("alpha", 1)
111
+
112
+ await conn.execute(
113
+ f"UPDATE {table} SET value = $1 WHERE name = $2", 11, "alpha"
114
+ )
115
+ assert (
116
+ await conn.fetchval(f"SELECT value FROM {table} WHERE name = $1", "alpha")
117
+ == 11
118
+ )
119
+
120
+ await conn.execute(f"DELETE FROM {table} WHERE name = $1", "alpha")
121
+ assert await conn.fetchval(f"SELECT COUNT(*) FROM {table}") == 0
122
+ finally:
123
+ try:
124
+ await conn.execute(f"DROP TABLE IF EXISTS {table}")
125
+ finally:
126
+ await conn.close()
127
+
128
+
64
129
  @pytest.mark.asyncio
65
130
  async def test_create_insert_select(env):
66
131
  conn = _connect(env)
@@ -0,0 +1,32 @@
1
+ """Bindings test worker.
2
+
3
+ Each binding suite lives in a `test_<suite>.py` module written as ordinary pytest
4
+ tests (see test_kv.py). The `/run-tests/<suite>` endpoint runs pytest against that
5
+ module inside workerd and returns per-test results as JSON, which the host-side
6
+ test_bindings.py maps onto individual pytest cases.
7
+
8
+ To add a new binding: create `src/test_<binding>.py` with pytest tests.
9
+ """
10
+
11
+ from testlib.entrypoint import TestRunnerEntrypoint
12
+ from worker_durable_object import (
13
+ TestDurableObject, # noqa: F401 - import to trigger side effect of registering the Durable Object
14
+ )
15
+ from worker_workflow import (
16
+ TestWorkflow, # noqa: F401 - import to trigger side effect of registering the Workflow
17
+ )
18
+
19
+ RECEIVED_MESSAGES = []
20
+
21
+
22
+ class Default(TestRunnerEntrypoint):
23
+ async def queue(self, batch, env, ctx):
24
+ for message in batch.messages:
25
+ RECEIVED_MESSAGES.append(
26
+ {
27
+ "id": message.id,
28
+ "body": message.body,
29
+ "attempts": message.attempts,
30
+ }
31
+ )
32
+ message.ack()
@@ -0,0 +1,116 @@
1
+ """Shared fixtures and helpers for the host-side test suite."""
2
+
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+ from collections.abc import Generator
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ import pytest
11
+ from testlib.host import (
12
+ COMPAT_CONFIGS,
13
+ CompatConfig,
14
+ configure_compatibility,
15
+ )
16
+ from testlib.host import (
17
+ dev_server as run_dev_server,
18
+ )
19
+ from testlib.host import (
20
+ register_in_worker_suites as register_testlib_suites,
21
+ )
22
+
23
+ TEST_DIR: Path = Path(__file__).parent
24
+ WORKERS_PY: Path = TEST_DIR.parent.parent / "cli"
25
+ WORKERS_RUNTIME_SDK: Path = TEST_DIR.parent / "src"
26
+ TESTLIB: Path = TEST_DIR.parent.parent / "testlib"
27
+
28
+ DEV_STARTUP_TIMEOUT: int = 120
29
+ OPT_IN_MARKERS: tuple[str, ...] = ("hyperdrive",)
30
+
31
+
32
+ def pytest_collection_modifyitems(
33
+ config: pytest.Config, items: list[pytest.Item]
34
+ ) -> None:
35
+ """Skip opt-in suites unless the run explicitly asks for them via ``-m``."""
36
+ markexpr: str = config.getoption("markexpr")
37
+ for marker in OPT_IN_MARKERS:
38
+ if marker in markexpr:
39
+ continue
40
+ skip = pytest.mark.skip(reason=f"needs local services; run with -m {marker}")
41
+ for item in items:
42
+ if marker in item.keywords:
43
+ item.add_marker(skip)
44
+
45
+
46
+ @pytest.fixture(scope="session", autouse=True)
47
+ def build_testlib():
48
+ subprocess.run(["uv", "build"], cwd=TESTLIB, check=True)
49
+
50
+
51
+ @pytest.fixture(
52
+ scope="module",
53
+ params=COMPAT_CONFIGS,
54
+ ids=[c.python_version for c in COMPAT_CONFIGS],
55
+ )
56
+ def compat_config(request: pytest.FixtureRequest) -> CompatConfig:
57
+ return request.param
58
+
59
+
60
+ @pytest.fixture(scope="module")
61
+ def worker_project_dir() -> Path:
62
+ """Worker project the `dev_server` fixture should serve.
63
+
64
+ Test modules using `dev_server` must override this fixture.
65
+ """
66
+ raise NotImplementedError(
67
+ "override the `worker_project_dir` fixture in your test module"
68
+ )
69
+
70
+
71
+ @pytest.fixture(scope="module")
72
+ def dev_server(
73
+ tmp_path_factory: pytest.TempPathFactory,
74
+ worker_project_dir: Path,
75
+ compat_config: CompatConfig,
76
+ ) -> Generator[str]:
77
+ """Start a pywrangler dev server on a free port and yield its base URL."""
78
+ tmp_path = tmp_path_factory.mktemp(f"{worker_project_dir.name}_dev")
79
+ target = tmp_path / worker_project_dir.name
80
+ shutil.copytree(worker_project_dir, target, ignore=shutil.ignore_patterns(".venv"))
81
+ shutil.copytree(TESTLIB, tmp_path / "testlib")
82
+ env = os.environ | {"_PYODIDE_EXTRA_MOUNTS": str(tmp_path)}
83
+
84
+ wrangler_jsonc = target / "wrangler.jsonc"
85
+ configure_compatibility(wrangler_jsonc, compat_config)
86
+
87
+ pywrangler_cmd = ["uv", "run", "--no-project", "--with", WORKERS_PY, "pywrangler"]
88
+
89
+ subprocess.run(
90
+ [*pywrangler_cmd, "sync"],
91
+ cwd=target,
92
+ check=True,
93
+ env=env,
94
+ )
95
+
96
+ shutil.copytree(WORKERS_RUNTIME_SDK, target / "python_modules", dirs_exist_ok=True)
97
+
98
+ with run_dev_server(
99
+ target,
100
+ tmp_path,
101
+ env,
102
+ pywrangler_cmd,
103
+ startup_timeout=DEV_STARTUP_TIMEOUT,
104
+ readiness_path="/health",
105
+ require_success=True,
106
+ log_name="dev.log",
107
+ ) as (base_url, _):
108
+ yield base_url
109
+
110
+
111
+ def register_in_worker_suites(
112
+ namespace: dict[str, Any],
113
+ src_dir: Path,
114
+ marks: dict[str, pytest.MarkDecorator] | None = None,
115
+ ) -> None:
116
+ register_testlib_suites(namespace, src_dir, marks=marks, class_name=str.upper)
@@ -4,9 +4,6 @@ Python 3.12 (Pyodide 0.26.0a2) is excluded. The in-worker pytest suite drives
4
4
  async tests via ``loop.run_until_complete``, which is a no-op on Pyodide 0.26.0a2
5
5
  (no ``run_sync``/JSPI): async tests return unawaited futures and report false
6
6
  passes.
7
-
8
- Python 3.14 is excluded because pydantic_core has a circular import error on
9
- the 3.14 Pyodide runtime (``validate_core_schema`` not found during module init).
10
7
  """
11
8
 
12
9
  from pathlib import Path
@@ -26,9 +23,8 @@ def worker_project_dir() -> Path:
26
23
 
27
24
 
28
25
  # Exclude Python 3.12 (Pyodide 0.26.0a2) for async tests.
29
- # Exclude Python 3.14 due to pydantic_core circular import error on Pyodide.
30
26
  FASTAPI_COMPAT_CONFIGS = [
31
- c for c in COMPAT_CONFIGS if c.python_version not in ("3.12", "3.14")
27
+ c for c in COMPAT_CONFIGS if c.python_version not in ("3.12",)
32
28
  ]
33
29
 
34
30
 
@@ -7,8 +7,7 @@ import pytest
7
7
  from conftest import (
8
8
  COMPAT_CONFIGS,
9
9
  CompatConfig,
10
- inject_compat_flags,
11
- replace_compat_date,
10
+ configure_compatibility,
12
11
  )
13
12
 
14
13
  TEST_DIR = Path(__file__).parent
@@ -30,6 +29,30 @@ def discover_workerd_tests():
30
29
  return cases
31
30
 
32
31
 
32
+ def resolve_workerd(target: Path) -> str:
33
+ """Return the path to the workerd binary to use for tests.
34
+
35
+ If the ``WORKERD_PATH`` environment variable is set, it is used as-is (this
36
+ is useful for testing against a locally built workerd). Otherwise, workerd
37
+ is installed from npm into ``target`` and the installed binary is used.
38
+ """
39
+ workerd_path = os.environ.get("WORKERD_PATH")
40
+ if workerd_path:
41
+ workerd_bin = Path(workerd_path).expanduser().resolve()
42
+ if not workerd_bin.is_file():
43
+ raise FileNotFoundError(
44
+ f"WORKERD_PATH is set but does not point to a file: {workerd_bin}"
45
+ )
46
+ return str(workerd_bin)
47
+
48
+ subprocess.run(
49
+ ["npm", "i", "workerd"],
50
+ cwd=target,
51
+ check=True,
52
+ )
53
+ return "node_modules/workerd/bin/workerd"
54
+
55
+
33
56
  def embed(dir: Path, root: Path, level: int = 0):
34
57
  modules = []
35
58
  module_path_root = dir
@@ -62,7 +85,7 @@ def bundle_cache_dir(tmp_path_factory):
62
85
  ids=[c.python_version for c in COMPAT_CONFIGS],
63
86
  )
64
87
  @pytest.mark.parametrize("test_dir, wd_test_file", discover_workerd_tests())
65
- def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
88
+ def test_in_workerd( # noqa: PLR0913, PLR0917 (too-many-arguments)
66
89
  tmp_path,
67
90
  test_dir,
68
91
  wd_test_file,
@@ -71,22 +94,25 @@ def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
71
94
  bundle_cache_dir,
72
95
  ):
73
96
  compat_date = compat_config.compat_date
97
+ python_version = compat_config.python_version
74
98
 
75
99
  # `wsgi` streams the request body via `pyodide.ffi.run_sync` (JSPI), which
76
100
  # is only available in newer Pyodide runtimes.
77
- if test_dir.name == "wsgi" and compat_date < "2026-01-01":
101
+ if test_dir.name == "wsgi" and python_version == "3.12":
78
102
  pytest.skip(
79
103
  "wsgi requires pyodide.ffi.run_sync (JSPI), unavailable before 2026-01-01"
80
104
  )
81
105
 
106
+ if test_dir.name == "http-client" and python_version < "3.14":
107
+ pytest.skip("HTTP client compatibility tests require Python 3.14 or newer")
108
+
82
109
  color = pytestconfig.get_terminal_writer().hasmarkup
83
110
  target = tmp_path / test_dir.name
84
111
  disk_service_dir = target / DISK_SERVICE_NAME
85
112
  shutil.copytree(test_dir, target, ignore=shutil.ignore_patterns(".venv"))
86
113
  disk_service_dir.mkdir(exist_ok=True)
87
114
 
88
- replace_compat_date(target / "wrangler.jsonc", compat_date)
89
- inject_compat_flags(target / "wrangler.jsonc", compat_config.extra_compat_flags)
115
+ configure_compatibility(target / "wrangler.jsonc", compat_config)
90
116
 
91
117
  pywrangler_cmd = ["uv", "run", "--no-project", "--with", WORKERS_PY, "pywrangler"]
92
118
 
@@ -114,15 +140,11 @@ def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
114
140
  .replace("%COLOR", str(color).lower())
115
141
  .replace("%COMPAT_DATE", compat_date)
116
142
  )
117
- inject_compat_flags(wd_config, compat_config.extra_compat_flags)
143
+ configure_compatibility(wd_config, compat_config)
118
144
 
119
- subprocess.run(
120
- ["npm", "i", "workerd"],
121
- cwd=target,
122
- check=True,
123
- )
145
+ workerd_bin = resolve_workerd(target)
124
146
  workerd_common = [
125
- "node_modules/workerd/bin/workerd",
147
+ workerd_bin,
126
148
  "test",
127
149
  wd_test_file,
128
150
  "--experimental",
@@ -10,4 +10,8 @@ dependencies = [
10
10
  "django-cors-headers",
11
11
  "pytest",
12
12
  "pytest-asyncio<1.2.0",
13
+ "testlib",
13
14
  ]
15
+
16
+ [tool.uv.sources]
17
+ testlib = { path = "../testlib/dist/testlib-0.0.0-py3-none-any.whl" }