workers-runtime-sdk 1.8.4__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 (192) hide show
  1. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/CHANGELOG.md +9 -0
  2. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/PKG-INFO +1 -1
  3. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/pyproject.toml +1 -1
  4. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_entropy_import_context.py +48 -0
  5. workers_runtime_sdk-1.8.5/tests/bindings-test/pyproject.toml +19 -0
  6. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_mysql.py +21 -0
  7. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_postgresql.py +65 -0
  8. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_in_workerd.py +28 -10
  9. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/worker.py +1 -1
  10. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +1 -3
  11. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/pyproject.toml +2 -0
  12. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_mcp.py +10 -0
  13. workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_opentelemetry.py +8 -0
  14. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/worker.py +2 -0
  15. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/http-client.wd-test +45 -0
  16. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/origin.py +60 -0
  17. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/pyproject.toml +5 -0
  18. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_http_client.py +162 -0
  19. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_urllib_request.py +121 -0
  20. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/worker.py +14 -0
  21. workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/wrangler.jsonc +5 -0
  22. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/uv.lock +1 -1
  23. workers_runtime_sdk-1.8.4/tests/bindings-test/pyproject.toml +0 -8
  24. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/.gitignore +0 -0
  25. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/AGENTS.md +0 -0
  26. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/README.md +0 -0
  27. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_cloudflare_compat_flags.pyi +0 -0
  28. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_pyodide_entrypoint_helper.pyi +0 -0
  29. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_package_patches.py +0 -0
  30. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.pth +0 -0
  31. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.py +0 -0
  32. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/asgi.py +0 -0
  33. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/__init__.py +0 -0
  34. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/asgi.py +0 -0
  35. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/blob.py +0 -0
  36. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/entrypoints.py +0 -0
  37. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/fetch.py +0 -0
  38. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/formdata.py +0 -0
  39. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/py.typed +0 -0
  40. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/request.py +0 -0
  41. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/response.py +0 -0
  42. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/rpc.py +0 -0
  43. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/types.py +0 -0
  44. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/utils.py +0 -0
  45. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/workflows.py +0 -0
  46. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/wsgi.py +0 -0
  47. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/data.json +0 -0
  48. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/hello.txt +0 -0
  49. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/conftest.py +0 -0
  50. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_analytics_engine.py +0 -0
  51. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_assets.py +0 -0
  52. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_d1.py +0 -0
  53. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_do.py +0 -0
  54. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_images.py +0 -0
  55. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_kv.py +0 -0
  56. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_mtls.py +0 -0
  57. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_queue.py +0 -0
  58. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_r2.py +0 -0
  59. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_ratelimit.py +0 -0
  60. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_vectorize.py +0 -0
  61. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_version_metadata.py +0 -0
  62. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_workflow.py +0 -0
  63. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker.py +0 -0
  64. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_durable_object.py +0 -0
  65. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_workflow.py +0 -0
  66. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/wrangler.jsonc +0 -0
  67. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/conftest.py +0 -0
  68. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_bindings.py +0 -0
  69. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_fastapi.py +0 -0
  70. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_flask.py +0 -0
  71. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_web_frameworks.py +0 -0
  72. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
  73. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
  74. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
  75. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
  76. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
  77. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
  78. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
  79. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
  80. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
  81. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
  82. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
  83. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
  84. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
  85. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
  86. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
  87. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
  88. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
  89. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
  90. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
  91. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
  92. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
  93. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
  94. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
  95. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
  96. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
  97. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
  98. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
  99. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
  100. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
  101. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
  102. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
  103. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
  104. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
  105. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
  106. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
  107. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
  108. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
  109. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
  110. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
  111. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
  112. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
  113. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
  114. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
  115. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
  116. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
  117. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
  118. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
  119. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
  120. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
  121. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
  122. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
  123. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
  124. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
  125. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
  126. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
  127. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
  128. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +0 -0
  129. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_boundaries.py +0 -0
  130. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_io.py +0 -0
  131. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +0 -0
  132. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +0 -0
  133. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +0 -0
  134. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
  135. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
  136. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +0 -0
  137. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
  138. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/pyproject.toml +0 -0
  139. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/src/test_response.py +0 -0
  140. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/src/worker.py +0 -0
  141. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/wrangler.jsonc +0 -0
  142. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/asgi.wd-test +0 -0
  143. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/pyproject.toml +0 -0
  144. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/tests/test_asgi.py +0 -0
  145. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/worker.py +0 -0
  146. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
  147. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
  148. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
  149. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
  150. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
  151. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
  152. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/pyproject.toml +0 -0
  153. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/worker.py +0 -0
  154. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
  155. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
  156. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
  157. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/worker.py +0 -0
  158. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
  159. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
  160. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
  161. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
  162. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
  163. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
  164. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
  165. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
  166. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
  167. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
  168. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
  169. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
  170. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
  171. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_litestar.py +0 -0
  172. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
  173. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
  174. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
  175. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
  176. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
  177. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
  178. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
  179. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.js +0 -0
  180. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.py +0 -0
  181. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
  182. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/pyproject.toml +0 -0
  183. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/sdk.wd-test +0 -0
  184. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/server.py +0 -0
  185. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
  186. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/worker.py +0 -0
  187. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
  188. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/pyproject.toml +0 -0
  189. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
  190. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/worker.py +0 -0
  191. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
  192. {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
@@ -2,6 +2,15 @@
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
+
5
14
  ## v1.8.4 (2026-09-08)
6
15
 
7
16
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: workers-runtime-sdk
3
- Version: 1.8.4
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.4"
7
+ version = "1.8.5"
8
8
  description = "Python SDK for Cloudflare Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -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
@@ -180,6 +204,30 @@ def langchain_openai_chat_models_base_context(module):
180
204
  yield
181
205
 
182
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
+
183
231
  @register_exec_patch("litestar.openapi.controller")
184
232
  @register_exec_patch("litestar.constants")
185
233
  @contextmanager
@@ -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)
@@ -29,6 +29,30 @@ def discover_workerd_tests():
29
29
  return cases
30
30
 
31
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
+
32
56
  def embed(dir: Path, root: Path, level: int = 0):
33
57
  modules = []
34
58
  module_path_root = dir
@@ -79,10 +103,8 @@ def test_in_workerd( # noqa: PLR0913, PLR0917 (too-many-arguments)
79
103
  "wsgi requires pyodide.ffi.run_sync (JSPI), unavailable before 2026-01-01"
80
104
  )
81
105
 
82
- if test_dir.name == "entropy-patches" and python_version == "3.14":
83
- pytest.skip(
84
- "TODO: enable me after https://github.com/cloudflare/workerd/pull/7200 lands in wrangler"
85
- )
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")
86
108
 
87
109
  color = pytestconfig.get_terminal_writer().hasmarkup
88
110
  target = tmp_path / test_dir.name
@@ -120,13 +142,9 @@ def test_in_workerd( # noqa: PLR0913, PLR0917 (too-many-arguments)
120
142
  )
121
143
  configure_compatibility(wd_config, compat_config)
122
144
 
123
- subprocess.run(
124
- ["npm", "i", "workerd"],
125
- cwd=target,
126
- check=True,
127
- )
145
+ workerd_bin = resolve_workerd(target)
128
146
  workerd_common = [
129
- "node_modules/workerd/bin/workerd",
147
+ workerd_bin,
130
148
  "test",
131
149
  wd_test_file,
132
150
  "--experimental",
@@ -602,7 +602,7 @@ class FastAPIAppPlugin:
602
602
 
603
603
  @app.get("/run-tests/{suite_name:path}")
604
604
  async def run_suite(suite_name: str, request: Request):
605
- runner = TestRunner(request.scope["env"])
605
+ runner = TestRunner(request.scope["env"], extra_plugins=[FastAPIAppPlugin()])
606
606
  result = runner.run_suite(suite_name)
607
607
  return JSONResponse(result.payload, status_code=result.status)
608
608
 
@@ -1,5 +1,6 @@
1
1
  import asyncio
2
2
  import contextlib
3
+ import json
3
4
 
4
5
  import pytest
5
6
  from pyodide.ffi import create_proxy, to_js
@@ -61,9 +62,6 @@ async def _ws_connect(path):
61
62
  )
62
63
 
63
64
 
64
- import json
65
-
66
-
67
65
  async def _events():
68
66
  response = await asyncio.wait_for(
69
67
  env.SELF.fetch("http://example.com/ws-events"), TIMEOUT_S
@@ -18,4 +18,6 @@ dependencies = [
18
18
  # "langchain-openai",
19
19
  # "openai",
20
20
  "litestar",
21
+ "opentelemetry-api",
22
+ "mcp; python_version >= '3.14'",
21
23
  ]
@@ -0,0 +1,10 @@
1
+ # ruff: noqa: F401
2
+ import sys
3
+
4
+ if sys.version_info >= (3, 14):
5
+ import mcp
6
+
7
+
8
+ def test_import():
9
+ # make sure this file is collected by pytest
10
+ pass
@@ -0,0 +1,8 @@
1
+ # ruff: noqa: F401
2
+ import opentelemetry.context
3
+ import opentelemetry.trace
4
+
5
+
6
+ def test_import():
7
+ # make sure this file is collected by pytest
8
+ pass
@@ -4,7 +4,9 @@ from tests import ( # noqa: F401
4
4
  test_aiohttp_websocket,
5
5
  test_langsmith,
6
6
  test_litestar,
7
+ test_mcp,
7
8
  test_numpy,
9
+ test_opentelemetry,
8
10
  test_pydantic,
9
11
  test_rust_packages,
10
12
  test_ssl_avoidance,
@@ -0,0 +1,45 @@
1
+ using Workerd = import "/workerd/workerd.capnp";
2
+
3
+ const client :Workerd.Worker = (
4
+ modules = [
5
+ (name = "worker.py", pythonModule = embed "worker.py"),
6
+ %PYTHON_MODULES
7
+ ],
8
+ bindings = [
9
+ (name = "color", json = "%COLOR"),
10
+ ],
11
+ globalOutbound = "external",
12
+ compatibilityDate = "%COMPAT_DATE",
13
+ compatibilityFlags = ["python_workers", "service_binding_extra_handlers"],
14
+ );
15
+
16
+ const origin :Workerd.Worker = (
17
+ modules = [
18
+ (name = "origin.py", pythonModule = embed "origin.py"),
19
+ %PYTHON_MODULES
20
+ ],
21
+ compatibilityDate = "%COMPAT_DATE",
22
+ compatibilityFlags = ["python_workers"],
23
+ );
24
+
25
+ const unitTests :Workerd.Config = (
26
+ services = [
27
+ (
28
+ name = "external",
29
+ external = (
30
+ address = "loopback:raw-http-origin",
31
+ tcp = (),
32
+ ),
33
+ ),
34
+ (name = "http-client", worker = .client),
35
+ (name = "http-origin", worker = .origin),
36
+ ],
37
+ sockets = [
38
+ (
39
+ name = "raw-http-origin",
40
+ address = "loopback:raw-http-origin",
41
+ http = (),
42
+ service = "http-origin",
43
+ ),
44
+ ],
45
+ );
@@ -0,0 +1,60 @@
1
+ import json
2
+
3
+ from workers import Response, WorkerEntrypoint
4
+
5
+
6
+ class Default(WorkerEntrypoint):
7
+ async def fetch(self, request):
8
+ url = request.url
9
+ path = url.split("?", 1)[0].rsplit("/", 1)[-1]
10
+
11
+ match path:
12
+ case "echo":
13
+ return Response.json(
14
+ {
15
+ "method": request.method,
16
+ "url": url,
17
+ "custom": request.headers.get("X-Custom"),
18
+ "content_type": request.headers.get("Content-Type"),
19
+ "body": (await request.bytes()).decode(),
20
+ }
21
+ )
22
+ case "body":
23
+ return Response(await request.text())
24
+ case "lines":
25
+ return Response("first\nsecond\nthird\n")
26
+ case "head":
27
+ return Response(
28
+ "body that HEAD must not expose", headers={"X-Origin": "head"}
29
+ )
30
+ case "redirect":
31
+ return Response(
32
+ "",
33
+ status=302,
34
+ headers={"Location": "http://example.com:80/final"},
35
+ )
36
+ case "final":
37
+ return Response("redirected")
38
+ case "error":
39
+ return Response(
40
+ "teapot body",
41
+ status=418,
42
+ status_text="I'm a Teapot",
43
+ headers={"X-Error": "expected"},
44
+ )
45
+ case "auth":
46
+ if request.headers.get("Authorization") != "Basic dXNlcjpwYXNz":
47
+ return Response(
48
+ "authentication required",
49
+ status=401,
50
+ headers={"WWW-Authenticate": 'Basic realm="compat"'},
51
+ )
52
+ return Response("authenticated")
53
+ case "set-cookie":
54
+ return Response(
55
+ "cookie set", headers={"Set-Cookie": "session=abc; Path=/"}
56
+ )
57
+ case "cookie":
58
+ return Response(request.headers.get("Cookie") or "")
59
+ case _:
60
+ return Response(json.dumps({"unexpected_url": url}), status=404)
@@ -0,0 +1,5 @@
1
+ [project]
2
+ name = "http-client-compatibility-test"
3
+ version = "0.0.0"
4
+ requires-python = ">=3.14"
5
+ dependencies = ["pytest"]
@@ -0,0 +1,162 @@
1
+ import http.client
2
+ import io
3
+ import json
4
+
5
+ import pytest
6
+
7
+ HOST = "example.com"
8
+ PORT = 80
9
+
10
+
11
+ def connection():
12
+ return http.client.HTTPConnection(HOST, PORT)
13
+
14
+
15
+ def get_json(response):
16
+ return json.loads(response.read())
17
+
18
+
19
+ def test_http_connection_explicit_connect_and_close():
20
+ conn = connection()
21
+ try:
22
+ conn.connect()
23
+ assert conn.sock is not None
24
+ finally:
25
+ conn.close()
26
+ assert conn.sock is None
27
+
28
+
29
+ def test_http_connection_lazy_connect_get_path_query_and_headers():
30
+ conn = connection()
31
+ try:
32
+ conn.request("GET", "/echo?name=workers", headers={"X-Custom": "present"})
33
+ payload = get_json(conn.getresponse())
34
+ finally:
35
+ conn.close()
36
+
37
+ assert payload == {
38
+ "method": "GET",
39
+ "url": "http://example.com/echo?name=workers",
40
+ "custom": "present",
41
+ "content_type": None,
42
+ "body": "",
43
+ }
44
+
45
+
46
+ @pytest.mark.parametrize(
47
+ "body", ["text body", b"bytes body", bytearray(b"bytearray body")]
48
+ )
49
+ def test_http_connection_post_string_and_bytes_like_bodies(body):
50
+ conn = connection()
51
+ try:
52
+ conn.request("POST", "/body", body=body)
53
+ expected = bytes(body, "latin-1") if isinstance(body, str) else bytes(body)
54
+ assert conn.getresponse().read() == expected
55
+ finally:
56
+ conn.close()
57
+
58
+
59
+ def test_http_connection_post_file_like_and_iterable_bodies():
60
+ for body in (io.BytesIO(b"file body"), [b"iter", b"able"]):
61
+ conn = connection()
62
+ try:
63
+ conn.request("POST", "/body", body=body, encode_chunked=True)
64
+ expected = b"file body" if hasattr(body, "read") else b"iterable"
65
+ assert conn.getresponse().read() == expected
66
+ finally:
67
+ conn.close()
68
+
69
+
70
+ def test_http_connection_low_level_request_assembly_and_send():
71
+ conn = connection()
72
+ try:
73
+ conn.putrequest("POST", "/echo")
74
+ conn.putheader("Content-Length", "3")
75
+ conn.putheader("X-Custom", "low-level")
76
+ conn.endheaders()
77
+ conn.send(b"raw")
78
+ assert get_json(conn.getresponse()) == {
79
+ "method": "POST",
80
+ "url": "http://example.com/echo",
81
+ "custom": "low-level",
82
+ "content_type": None,
83
+ "body": "raw",
84
+ }
85
+ finally:
86
+ conn.close()
87
+
88
+
89
+ def test_http_response_metadata_and_headers():
90
+ conn = connection()
91
+ try:
92
+ conn.request("GET", "/echo")
93
+ response = conn.getresponse()
94
+ assert response.status == 200
95
+ assert response.reason == "OK"
96
+ assert response.version == 11
97
+ assert response.getheader("content-type") == "application/json"
98
+ assert response.getheaders()
99
+ response.read()
100
+ finally:
101
+ conn.close()
102
+
103
+
104
+ def test_http_response_read_methods_and_peek():
105
+ conn = connection()
106
+ try:
107
+ conn.request("GET", "/lines")
108
+ response = conn.getresponse()
109
+ assert response.peek(5).startswith(b"first")
110
+ assert response.read(5) == b"first"
111
+ target = bytearray(1)
112
+ assert response.readinto(target) == 1
113
+ assert target == b"\n"
114
+ assert response.read1(6) == b"second"
115
+ assert response.read() == b"\nthird\n"
116
+ finally:
117
+ conn.close()
118
+
119
+
120
+ def test_http_response_line_iteration():
121
+ conn = connection()
122
+ try:
123
+ conn.request("GET", "/lines")
124
+ assert list(conn.getresponse()) == [b"first\n", b"second\n", b"third\n"]
125
+ finally:
126
+ conn.close()
127
+
128
+
129
+ def test_http_connection_head_has_no_response_body():
130
+ conn = connection()
131
+ try:
132
+ conn.request("HEAD", "/head")
133
+ response = conn.getresponse()
134
+ assert response.status == 200
135
+ assert response.getheader("X-Origin") == "head"
136
+ assert response.read() == b""
137
+ finally:
138
+ conn.close()
139
+
140
+
141
+ def test_http_connection_reuse_and_reconnect_after_close():
142
+ conn = connection()
143
+ try:
144
+ conn.request("GET", "/body")
145
+ assert conn.getresponse().read() == b""
146
+ conn.request("GET", "/lines")
147
+ assert conn.getresponse().read() == b"first\nsecond\nthird\n"
148
+ conn.close()
149
+ conn.request("GET", "/final")
150
+ assert conn.getresponse().read() == b"redirected"
151
+ finally:
152
+ conn.close()
153
+
154
+
155
+ def test_http_connection_state_and_validation_errors():
156
+ conn = connection()
157
+ with pytest.raises(http.client.ResponseNotReady):
158
+ conn.getresponse()
159
+ with pytest.raises(http.client.CannotSendHeader):
160
+ conn.putheader("X-Test", "value")
161
+ with pytest.raises(ValueError):
162
+ conn.request("GET\n", "/echo")