workers-runtime-sdk 1.6.13__tar.gz → 1.6.14__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 (175) hide show
  1. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/CHANGELOG.md +8 -0
  2. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/PKG-INFO +1 -1
  3. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/pyproject.toml +4 -1
  4. workers_runtime_sdk-1.6.14/src/asgi.py +6 -0
  5. {workers_runtime_sdk-1.6.13/src → workers_runtime_sdk-1.6.14/src/workers}/asgi.py +15 -9
  6. workers_runtime_sdk-1.6.14/tests/bindings-test/pyproject.toml +5 -0
  7. {workers_runtime_sdk-1.6.13/tests/web-frameworks-test/fastapi-tests → workers_runtime_sdk-1.6.14/tests/bindings-test}/src/conftest.py +6 -0
  8. workers_runtime_sdk-1.6.14/tests/bindings-test/src/test_hyperdrive_mysql.py +208 -0
  9. workers_runtime_sdk-1.6.14/tests/bindings-test/src/test_hyperdrive_postgresql.py +182 -0
  10. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/wrangler.jsonc +12 -0
  11. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/conftest.py +25 -2
  12. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/test_bindings.py +9 -1
  13. workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +156 -0
  14. workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +12 -0
  15. workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +183 -0
  16. workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +190 -0
  17. workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests/src/worker.py +560 -0
  18. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi/tests/test_asgi.py +7 -0
  19. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/uv.lock +1 -1
  20. workers_runtime_sdk-1.6.13/tests/bindings-test/pyproject.toml +0 -5
  21. workers_runtime_sdk-1.6.13/tests/web-frameworks-test/fastapi-tests/src/worker.py +0 -251
  22. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/.gitignore +0 -0
  23. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/AGENTS.md +0 -0
  24. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/README.md +0 -0
  25. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_cloudflare_compat_flags.pyi +0 -0
  26. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_pyodide_entrypoint_helper.pyi +0 -0
  27. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_workers_sdk_entropy_import_context.py +0 -0
  28. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_workers_sdk_package_patches.py +0 -0
  29. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_workers_sdk_patch_loader.pth +0 -0
  30. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/_workers_sdk_patch_loader.py +0 -0
  31. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/__init__.py +0 -0
  32. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/blob.py +0 -0
  33. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/entrypoints.py +0 -0
  34. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/fetch.py +0 -0
  35. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/formdata.py +0 -0
  36. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/py.typed +0 -0
  37. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/request.py +0 -0
  38. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/response.py +0 -0
  39. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/rpc.py +0 -0
  40. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/types.py +0 -0
  41. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/utils.py +0 -0
  42. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/workflows.py +0 -0
  43. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/src/workers/wsgi.py +0 -0
  44. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/public/data.json +0 -0
  45. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/public/hello.txt +0 -0
  46. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_analytics_engine.py +0 -0
  47. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_assets.py +0 -0
  48. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_d1.py +0 -0
  49. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_do.py +0 -0
  50. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_images.py +0 -0
  51. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_kv.py +0 -0
  52. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_mtls.py +0 -0
  53. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_queue.py +0 -0
  54. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_r2.py +0 -0
  55. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_ratelimit.py +0 -0
  56. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_vectorize.py +0 -0
  57. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_version_metadata.py +0 -0
  58. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/test_workflow.py +0 -0
  59. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/worker.py +0 -0
  60. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/worker_durable_object.py +0 -0
  61. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/bindings-test/src/worker_workflow.py +0 -0
  62. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/test_fastapi.py +0 -0
  63. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/test_in_workerd.py +0 -0
  64. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/test_web_frameworks.py +0 -0
  65. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
  66. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
  67. {workers_runtime_sdk-1.6.13/tests/bindings-test → workers_runtime_sdk-1.6.14/tests/web-frameworks-test/django-async}/src/conftest.py +0 -0
  68. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
  69. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
  70. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
  71. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
  72. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
  73. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
  74. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
  75. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
  76. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
  77. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
  78. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
  79. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
  80. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
  81. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
  82. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
  83. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
  84. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
  85. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
  86. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
  87. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
  88. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
  89. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
  90. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
  91. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
  92. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
  93. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
  94. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
  95. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
  96. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
  97. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
  98. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
  99. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
  100. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
  101. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
  102. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
  103. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
  104. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
  105. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
  106. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
  107. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
  108. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
  109. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
  110. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
  111. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
  112. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
  113. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
  114. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
  115. {workers_runtime_sdk-1.6.13/tests/web-frameworks-test/django-async → workers_runtime_sdk-1.6.14/tests/web-frameworks-test/fastapi-tests}/src/conftest.py +0 -0
  116. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
  117. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
  118. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
  119. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
  120. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
  121. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
  122. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
  123. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
  124. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi/asgi.wd-test +0 -0
  125. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi/pyproject.toml +0 -0
  126. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi/worker.py +0 -0
  127. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
  128. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
  129. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
  130. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +0 -0
  131. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
  132. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
  133. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
  134. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object/pyproject.toml +0 -0
  135. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object/worker.py +0 -0
  136. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
  137. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
  138. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
  139. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-abort/worker.py +0 -0
  140. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
  141. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
  142. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
  143. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
  144. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
  145. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
  146. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
  147. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
  148. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
  149. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
  150. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
  151. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/pyproject.toml +0 -0
  152. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
  153. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
  154. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
  155. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
  156. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
  157. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
  158. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/worker.py +0 -0
  159. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
  160. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
  161. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
  162. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/python-rpc/worker.js +0 -0
  163. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/python-rpc/worker.py +0 -0
  164. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
  165. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/pyproject.toml +0 -0
  166. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/sdk.wd-test +0 -0
  167. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/server.py +0 -0
  168. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
  169. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/worker.py +0 -0
  170. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
  171. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/wsgi/pyproject.toml +0 -0
  172. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
  173. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/wsgi/worker.py +0 -0
  174. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
  175. {workers_runtime_sdk-1.6.13 → workers_runtime_sdk-1.6.14}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
@@ -2,6 +2,14 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.6.14 (2026-08-19)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Fixes fastapi lifespan state not persisting
10
+ ([`fadd19b`](https://github.com/cloudflare/workers-py/commit/fadd19bcb6ca47518d5e42562879164dd62ab404))
11
+
12
+
5
13
  ## v1.6.13 (2026-08-12)
6
14
 
7
15
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: workers-runtime-sdk
3
- Version: 1.6.13
3
+ Version: 1.6.14
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.13"
7
+ version = "1.6.14"
8
8
  description = "Python SDK for Cloudflare Workers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -64,6 +64,9 @@ lint.per-file-ignores."tests/web-frameworks-test/**" = ["C901", "PLR0911", "PLR0
64
64
 
65
65
  [tool.pytest.ini_options]
66
66
  addopts = ["--ignore=tests/workerd-test", "--ignore=tests/bindings-test", "--ignore=tests/web-frameworks-test"]
67
+ markers = [
68
+ "hyperdrive: needs MySQL and PostgreSQL on localhost; skipped unless run with -m hyperdrive",
69
+ ]
67
70
 
68
71
  [tool.mypy]
69
72
  packages = ["workers_runtime_sdk"]
@@ -0,0 +1,6 @@
1
+ # Compatibility module for existing code that imports `asgi` directly.
2
+ import sys
3
+
4
+ from workers import asgi as _asgi
5
+
6
+ sys.modules[__name__] = _asgi
@@ -49,7 +49,7 @@ def acquire_js_buffer(pybuffer):
49
49
  buf.release()
50
50
 
51
51
 
52
- def request_to_scope(req, env, ws=False):
52
+ def request_to_scope(req, env, ws=False, state=None):
53
53
  from js import URL
54
54
 
55
55
  # @app.get("/example")
@@ -74,7 +74,7 @@ def request_to_scope(req, env, ws=False):
74
74
  ty = "websocket"
75
75
  else:
76
76
  ty = "http"
77
- return {
77
+ scope = {
78
78
  "asgi": ASGI,
79
79
  "headers": headers,
80
80
  "http_version": "1.1",
@@ -86,6 +86,10 @@ def request_to_scope(req, env, ws=False):
86
86
  "type": ty,
87
87
  "env": env,
88
88
  }
89
+ if state is not None:
90
+ # ASGI requires a shallow copy of lifespan state for each request.
91
+ scope["state"] = dict(state)
92
+ return scope
89
93
 
90
94
 
91
95
  async def start_application(app):
@@ -94,6 +98,7 @@ async def start_application(app):
94
98
  # don't implement it and fall back to serving requests without lifespan.
95
99
  # https://asgi.readthedocs.io/en/latest/specs/lifespan.html
96
100
  receive_queue = Queue()
101
+ state = {}
97
102
  await receive_queue.put({"type": "lifespan.startup"})
98
103
 
99
104
  # `startup` resolves True on `lifespan.startup.complete`, False when the app
@@ -141,7 +146,7 @@ async def start_application(app):
141
146
  await app(
142
147
  {
143
148
  "asgi": ASGI,
144
- "state": {},
149
+ "state": state,
145
150
  "type": "lifespan",
146
151
  },
147
152
  receive,
@@ -168,17 +173,18 @@ async def start_application(app):
168
173
  run_in_background(run_lifespan())
169
174
  supported = await startup
170
175
  if not supported:
171
- return no_lifespan_shutdown
172
- return shutdown
176
+ return no_lifespan_shutdown, state
177
+ return shutdown, state
173
178
 
174
179
 
175
- async def process_request(
180
+ async def process_request( # noqa: PLR0913
176
181
  app: Any,
177
182
  req: "Request | js.Request",
178
183
  env: Any,
179
184
  # added for waitUntil, but not used anymore
180
185
  # TODO(later): remove this parameter after unvendoring Python SDK from workerd
181
186
  ctx: Context | None,
187
+ state: dict[str, Any] | None = None,
182
188
  ) -> js.Response:
183
189
  from js import Response, TransformStream
184
190
  from pyodide.ffi import create_proxy
@@ -273,7 +279,7 @@ async def process_request(
273
279
  # Run the application in the background
274
280
  async def run_app():
275
281
  try:
276
- await app(request_to_scope(req, env), receive, send)
282
+ await app(request_to_scope(req, env, state=state), receive, send)
277
283
 
278
284
  # If we get here and no response has been set yet, the app didn't generate a response
279
285
  if not result.done():
@@ -380,9 +386,9 @@ async def fetch(
380
386
  app: Any, req: "Request | js.Request", env: Any, ctx: Context | None = None
381
387
  ) -> js.Response:
382
388
  logger.debug("ASGI request: %s %s", req.method, req.url)
383
- shutdown = await start_application(app)
389
+ shutdown, state = await start_application(app)
384
390
  try:
385
- result = await process_request(app, req, env, ctx)
391
+ result = await process_request(app, req, env, ctx, state=state)
386
392
  except Exception:
387
393
  logger.exception("ASGI request failed")
388
394
  raise
@@ -0,0 +1,5 @@
1
+ [project]
2
+ name = "bindings-test"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.12"
5
+ dependencies = ["pytest", "pytest-asyncio<1.2.0", "pg8000", "pymysql", "cryptography"]
@@ -1,4 +1,5 @@
1
1
  # pyright: reportMissingImports=false
2
+ import uuid
2
3
 
3
4
  import pytest
4
5
 
@@ -8,3 +9,8 @@ from workers import env as _env
8
9
  @pytest.fixture
9
10
  def env():
10
11
  return _env
12
+
13
+
14
+ def unique_table_name() -> str:
15
+ """Unique per call"""
16
+ return f"test_{uuid.uuid4().hex[:10]}"
@@ -0,0 +1,208 @@
1
+ # pyright: reportMissingImports=false
2
+
3
+ """
4
+ This test requires a MySQL server to be running on localhost.
5
+
6
+ Run mysql with docker:
7
+
8
+ docker run -d --name mysql \
9
+ -e MYSQL_ROOT_PASSWORD=rootpass \
10
+ -e MYSQL_USER=testuser \
11
+ -e MYSQL_PASSWORD=testpass \
12
+ -e MYSQL_DATABASE=testdb \
13
+ -p 3306:3306 \
14
+ --health-cmd="mysqladmin ping -h 127.0.0.1" \
15
+ --health-interval=10s \
16
+ --health-timeout=5s \
17
+ --health-retries=5 \
18
+ mysql:8.4
19
+
20
+ Then run the test:
21
+
22
+ uv run pytest tests/test_bindings.py -m hyperdrive -k mysql
23
+ """
24
+
25
+ import sys
26
+
27
+ import pymysql
28
+ import pytest
29
+ from conftest import unique_table_name
30
+
31
+
32
+ @pytest.fixture(autouse=True)
33
+ def skip_if_no_socket_support():
34
+ if sys.version_info.minor < 14:
35
+ pytest.skip("Socket support requires Python 3.14+")
36
+
37
+
38
+ def _connect(env):
39
+ hd = env.HYPERDRIVE_MYSQL
40
+ return pymysql.connect(
41
+ host=hd.host,
42
+ port=int(hd.port),
43
+ user=hd.user,
44
+ password=hd.password,
45
+ database=hd.database,
46
+ unix_socket=False,
47
+ # Hyperdrive terminates TLS to the origin, so this hop is plaintext.
48
+ ssl_disabled=True,
49
+ )
50
+
51
+
52
+ @pytest.mark.asyncio
53
+ async def test_connect(env):
54
+ conn = _connect(env)
55
+ cur = conn.cursor()
56
+ cur.execute("SELECT 1")
57
+ assert cur.fetchone() == (1,)
58
+ conn.close()
59
+
60
+
61
+ @pytest.mark.asyncio
62
+ async def test_create_insert_select(env):
63
+ conn = _connect(env)
64
+ table = unique_table_name()
65
+ cur = conn.cursor()
66
+ try:
67
+ cur.execute(
68
+ f"CREATE TABLE {table} "
69
+ "(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), value INT)"
70
+ )
71
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("alpha", 1))
72
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("beta", 2))
73
+ conn.commit()
74
+
75
+ cur.execute(f"SELECT name, value FROM {table} ORDER BY name")
76
+ assert cur.fetchall() == (("alpha", 1), ("beta", 2))
77
+ finally:
78
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
79
+ conn.commit()
80
+ conn.close()
81
+
82
+
83
+ @pytest.mark.asyncio
84
+ async def test_update(env):
85
+ conn = _connect(env)
86
+ table = unique_table_name()
87
+ cur = conn.cursor()
88
+ try:
89
+ cur.execute(
90
+ f"CREATE TABLE {table} "
91
+ "(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), value INT)"
92
+ )
93
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("alpha", 1))
94
+ conn.commit()
95
+
96
+ cur.execute(
97
+ f"UPDATE {table} SET value = value + 10 WHERE name = %s", ("alpha",)
98
+ )
99
+ conn.commit()
100
+
101
+ cur.execute(f"SELECT value FROM {table} WHERE name = %s", ("alpha",))
102
+ assert cur.fetchone() == (11,)
103
+ finally:
104
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
105
+ conn.commit()
106
+ conn.close()
107
+
108
+
109
+ @pytest.mark.asyncio
110
+ async def test_delete(env):
111
+ conn = _connect(env)
112
+ table = unique_table_name()
113
+ cur = conn.cursor()
114
+ try:
115
+ cur.execute(
116
+ f"CREATE TABLE {table} (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100))"
117
+ )
118
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("alpha",))
119
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("beta",))
120
+ conn.commit()
121
+
122
+ cur.execute(f"DELETE FROM {table} WHERE name = %s", ("alpha",))
123
+ conn.commit()
124
+
125
+ cur.execute(f"SELECT name FROM {table}")
126
+ assert cur.fetchall() == (("beta",),)
127
+ finally:
128
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
129
+ conn.commit()
130
+ conn.close()
131
+
132
+
133
+ @pytest.mark.asyncio
134
+ async def test_transaction_rollback(env):
135
+ conn = _connect(env)
136
+ table = unique_table_name()
137
+ cur = conn.cursor()
138
+ try:
139
+ cur.execute(
140
+ f"CREATE TABLE {table} "
141
+ "(id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100)) ENGINE=InnoDB"
142
+ )
143
+ conn.commit()
144
+
145
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("should_disappear",))
146
+ conn.rollback()
147
+
148
+ cur.execute(f"SELECT COUNT(*) FROM {table}")
149
+ assert cur.fetchone() == (0,)
150
+ finally:
151
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
152
+ conn.commit()
153
+ conn.close()
154
+
155
+
156
+ @pytest.mark.asyncio
157
+ async def test_multiple_data_types(env):
158
+ conn = _connect(env)
159
+ table = unique_table_name()
160
+ cur = conn.cursor()
161
+ try:
162
+ cur.execute(
163
+ f"CREATE TABLE {table} ("
164
+ "id INT AUTO_INCREMENT PRIMARY KEY, "
165
+ "text_col VARCHAR(255), "
166
+ "int_col INT, "
167
+ "float_col DOUBLE, "
168
+ "bool_col BOOLEAN)"
169
+ )
170
+ cur.execute(
171
+ f"INSERT INTO {table} (text_col, int_col, float_col, bool_col) "
172
+ "VALUES (%s, %s, %s, %s)",
173
+ ("hello", 42, 3.14, True),
174
+ )
175
+ conn.commit()
176
+
177
+ cur.execute(f"SELECT text_col, int_col, float_col, bool_col FROM {table}")
178
+ row = cur.fetchone()
179
+ assert row[0] == "hello"
180
+ assert row[1] == 42
181
+ assert abs(row[2] - 3.14) < 0.001
182
+ assert row[3] == 1
183
+ finally:
184
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
185
+ conn.commit()
186
+ conn.close()
187
+
188
+
189
+ @pytest.mark.asyncio
190
+ async def test_executemany(env):
191
+ conn = _connect(env)
192
+ table = unique_table_name()
193
+ cur = conn.cursor()
194
+ try:
195
+ cur.execute(
196
+ f"CREATE TABLE {table} (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100))"
197
+ )
198
+ cur.executemany(
199
+ f"INSERT INTO {table} (name) VALUES (%s)", [("a",), ("b",), ("c",)]
200
+ )
201
+ conn.commit()
202
+
203
+ cur.execute(f"SELECT name FROM {table} ORDER BY name")
204
+ assert cur.fetchall() == (("a",), ("b",), ("c",))
205
+ finally:
206
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
207
+ conn.commit()
208
+ conn.close()
@@ -0,0 +1,182 @@
1
+ # pyright: reportMissingImports=false
2
+
3
+ """
4
+ This test requires a PostgreSQL server to be running on localhost.
5
+
6
+ Run postgresql with docker:
7
+
8
+ docker run -d --name postgres \
9
+ -e POSTGRES_USER=testuser \
10
+ -e POSTGRES_PASSWORD=testpass \
11
+ -e POSTGRES_DB=testdb \
12
+ -e POSTGRES_HOST_AUTH_METHOD=md5 \
13
+ -e POSTGRES_INITDB_ARGS="--auth-host=md5" \
14
+ -p 5432:5432 \
15
+ --health-cmd="pg_isready -U testuser -d testdb" \
16
+ --health-interval=10s \
17
+ --health-timeout=5s \
18
+ --health-retries=5 \
19
+ postgres:16
20
+
21
+ Then run the test:
22
+
23
+ uv run pytest tests/test_bindings.py -m hyperdrive -k postgresql
24
+
25
+ Note: "POSTGRES_HOST_AUTH_METHOD=md5" is required for PostgreSQL to work with pg8000, since the
26
+ default `scram-sha-256` is not available in the pg8000 with Python workers (missing openssl)
27
+ """
28
+
29
+ import sys
30
+
31
+ import pg8000
32
+ import pytest
33
+ from conftest import unique_table_name
34
+
35
+
36
+ @pytest.fixture(autouse=True)
37
+ def skip_if_no_socket_support():
38
+ if sys.version_info.minor < 14:
39
+ pytest.skip("Socket support requires Python 3.14+")
40
+
41
+
42
+ def _connect(env):
43
+ hd = env.HYPERDRIVE_PG
44
+ return pg8000.connect(
45
+ host=hd.host,
46
+ port=int(hd.port),
47
+ user=hd.user,
48
+ password=hd.password,
49
+ database=hd.database,
50
+ # Hyperdrive terminates TLS to the origin, so this hop is plaintext.
51
+ ssl_context=False,
52
+ )
53
+
54
+
55
+ @pytest.mark.asyncio
56
+ async def test_connect(env):
57
+ conn = _connect(env)
58
+ cur = conn.cursor()
59
+ cur.execute("SELECT 1")
60
+ assert cur.fetchone() == [1]
61
+ conn.close()
62
+
63
+
64
+ @pytest.mark.asyncio
65
+ async def test_create_insert_select(env):
66
+ conn = _connect(env)
67
+ table = unique_table_name()
68
+ cur = conn.cursor()
69
+ try:
70
+ cur.execute(
71
+ f"CREATE TABLE {table} (id SERIAL PRIMARY KEY, name TEXT, value INT)"
72
+ )
73
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("alpha", 1))
74
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("beta", 2))
75
+ conn.commit()
76
+
77
+ cur.execute(f"SELECT name, value FROM {table} ORDER BY name")
78
+ assert list(cur.fetchall()) == [["alpha", 1], ["beta", 2]]
79
+ finally:
80
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
81
+ conn.commit()
82
+ conn.close()
83
+
84
+
85
+ @pytest.mark.asyncio
86
+ async def test_update(env):
87
+ conn = _connect(env)
88
+ table = unique_table_name()
89
+ cur = conn.cursor()
90
+ try:
91
+ cur.execute(
92
+ f"CREATE TABLE {table} (id SERIAL PRIMARY KEY, name TEXT, value INT)"
93
+ )
94
+ cur.execute(f"INSERT INTO {table} (name, value) VALUES (%s, %s)", ("alpha", 1))
95
+ conn.commit()
96
+
97
+ cur.execute(
98
+ f"UPDATE {table} SET value = value + 10 WHERE name = %s", ("alpha",)
99
+ )
100
+ conn.commit()
101
+
102
+ cur.execute(f"SELECT value FROM {table} WHERE name = %s", ("alpha",))
103
+ assert cur.fetchone() == [11]
104
+ finally:
105
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
106
+ conn.commit()
107
+ conn.close()
108
+
109
+
110
+ @pytest.mark.asyncio
111
+ async def test_delete(env):
112
+ conn = _connect(env)
113
+ table = unique_table_name()
114
+ cur = conn.cursor()
115
+ try:
116
+ cur.execute(f"CREATE TABLE {table} (id SERIAL PRIMARY KEY, name TEXT)")
117
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("alpha",))
118
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("beta",))
119
+ conn.commit()
120
+
121
+ cur.execute(f"DELETE FROM {table} WHERE name = %s", ("alpha",))
122
+ conn.commit()
123
+
124
+ cur.execute(f"SELECT name FROM {table}")
125
+ assert list(cur.fetchall()) == [["beta"]]
126
+ finally:
127
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
128
+ conn.commit()
129
+ conn.close()
130
+
131
+
132
+ @pytest.mark.asyncio
133
+ async def test_transaction_rollback(env):
134
+ conn = _connect(env)
135
+ table = unique_table_name()
136
+ cur = conn.cursor()
137
+ try:
138
+ cur.execute(f"CREATE TABLE {table} (id SERIAL PRIMARY KEY, name TEXT)")
139
+ conn.commit()
140
+
141
+ cur.execute(f"INSERT INTO {table} (name) VALUES (%s)", ("should_disappear",))
142
+ conn.rollback()
143
+
144
+ cur.execute(f"SELECT COUNT(*) FROM {table}")
145
+ assert cur.fetchone() == [0]
146
+ finally:
147
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
148
+ conn.commit()
149
+ conn.close()
150
+
151
+
152
+ @pytest.mark.asyncio
153
+ async def test_multiple_data_types(env):
154
+ conn = _connect(env)
155
+ table = unique_table_name()
156
+ cur = conn.cursor()
157
+ try:
158
+ cur.execute(
159
+ f"CREATE TABLE {table} ("
160
+ "id SERIAL PRIMARY KEY, "
161
+ "text_col TEXT, "
162
+ "int_col INT, "
163
+ "float_col DOUBLE PRECISION, "
164
+ "bool_col BOOLEAN)"
165
+ )
166
+ cur.execute(
167
+ f"INSERT INTO {table} (text_col, int_col, float_col, bool_col) "
168
+ "VALUES (%s, %s, %s, %s)",
169
+ ("hello", 42, 3.14, True),
170
+ )
171
+ conn.commit()
172
+
173
+ cur.execute(f"SELECT text_col, int_col, float_col, bool_col FROM {table}")
174
+ row = cur.fetchone()
175
+ assert row[0] == "hello"
176
+ assert row[1] == 42
177
+ assert abs(row[2] - 3.14) < 0.001
178
+ assert row[3] is True
179
+ finally:
180
+ cur.execute(f"DROP TABLE IF EXISTS {table}")
181
+ conn.commit()
182
+ conn.close()
@@ -49,6 +49,18 @@
49
49
  "analytics_engine_datasets": [
50
50
  { "binding": "ANALYTICS", "dataset": "test-dataset" }
51
51
  ],
52
+ "hyperdrive": [
53
+ {
54
+ "binding": "HYPERDRIVE_PG",
55
+ "id": "00000000-0000-0000-0000-000000000001",
56
+ "localConnectionString": "postgres://testuser:testpass@127.0.0.1:5432/testdb"
57
+ },
58
+ {
59
+ "binding": "HYPERDRIVE_MYSQL",
60
+ "id": "00000000-0000-0000-0000-000000000002",
61
+ "localConnectionString": "mysql://testuser:testpass@127.0.0.1:3306/testdb"
62
+ }
63
+ ],
52
64
  "images": { "binding": "IMAGES" },
53
65
  "ratelimits": [
54
66
  { "name": "RATE_LIMITER", "namespace_id": "1001", "simple": { "period": 60, "limit": 100 } }
@@ -24,6 +24,22 @@ DEV_POLL_INTERVAL: float = 0.5
24
24
  SUITE_CONNECT_TIMEOUT: int = 10
25
25
  SUITE_READ_TIMEOUT: int = 300
26
26
 
27
+ OPT_IN_MARKERS: tuple[str, ...] = ("hyperdrive",)
28
+
29
+
30
+ def pytest_collection_modifyitems(
31
+ config: pytest.Config, items: list[pytest.Item]
32
+ ) -> None:
33
+ """Skip opt-in suites unless the run explicitly asks for them via ``-m``."""
34
+ markexpr: str = config.getoption("markexpr")
35
+ for marker in OPT_IN_MARKERS:
36
+ if marker in markexpr:
37
+ continue
38
+ skip = pytest.mark.skip(reason=f"needs local services; run with -m {marker}")
39
+ for item in items:
40
+ if marker in item.keywords:
41
+ item.add_marker(skip)
42
+
27
43
 
28
44
  @dataclass(frozen=True)
29
45
  class CompatConfig:
@@ -256,12 +272,19 @@ def discover_suites(src_dir: Path) -> dict[str, list[str]]:
256
272
  }
257
273
 
258
274
 
259
- def register_in_worker_suites(namespace: dict[str, Any], src_dir: Path) -> None:
275
+ def register_in_worker_suites(
276
+ namespace: dict[str, Any],
277
+ src_dir: Path,
278
+ marks: dict[str, pytest.MarkDecorator] | None = None,
279
+ ) -> None:
260
280
  """Define a ``TestXxx`` class in `namespace` for every suite found in `src_dir`.
261
281
 
262
282
  Call with ``globals()`` from a test module so each in-worker test surfaces as
263
- its own pytest case without manual registration.
283
+ its own pytest case without manual registration. `marks` applies a marker to
284
+ the class generated for the suite of the same name.
264
285
  """
265
286
  for suite, test_names in discover_suites(src_dir).items():
266
287
  suite_cls = make_suite_class(suite, test_names)
288
+ if marks and suite in marks:
289
+ suite_cls = marks[suite](suite_cls)
267
290
  namespace[suite_cls.__name__] = suite_cls
@@ -18,10 +18,18 @@ from conftest import register_in_worker_suites
18
18
  BINDINGS_TEST_DIR: Path = Path(__file__).parent / "bindings-test"
19
19
  BINDINGS_SRC_DIR: Path = BINDINGS_TEST_DIR / "src"
20
20
 
21
+ SUITE_MARKS: dict[str, pytest.MarkDecorator] = {
22
+ # hyperdrive tests require external databases to be running
23
+ # so it is skipped by default.
24
+ # See each test file for details on how to run them.
25
+ "hyperdrive_postgresql": pytest.mark.hyperdrive,
26
+ "hyperdrive_mysql": pytest.mark.hyperdrive,
27
+ }
28
+
21
29
 
22
30
  @pytest.fixture(scope="module")
23
31
  def worker_project_dir() -> Path:
24
32
  return BINDINGS_TEST_DIR
25
33
 
26
34
 
27
- register_in_worker_suites(globals(), BINDINGS_SRC_DIR)
35
+ register_in_worker_suites(globals(), BINDINGS_SRC_DIR, marks=SUITE_MARKS)