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.
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/CHANGELOG.md +9 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/pyproject.toml +1 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_entropy_import_context.py +48 -0
- workers_runtime_sdk-1.8.5/tests/bindings-test/pyproject.toml +19 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_mysql.py +21 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_hyperdrive_postgresql.py +65 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_in_workerd.py +28 -10
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/worker.py +1 -1
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/pyproject.toml +2 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_mcp.py +10 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/entropy-patches/tests/test_opentelemetry.py +8 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/worker.py +2 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/http-client.wd-test +45 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/origin.py +60 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/pyproject.toml +5 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_http_client.py +162 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/tests/test_urllib_request.py +121 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/worker.py +14 -0
- workers_runtime_sdk-1.8.5/tests/workerd-test/http-client/wrangler.jsonc +5 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/uv.lock +1 -1
- workers_runtime_sdk-1.8.4/tests/bindings-test/pyproject.toml +0 -8
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/.gitignore +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/AGENTS.md +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/README.md +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_package_patches.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.pth +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_patch_loader.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/entrypoints.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/request.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/response.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/utils.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/workers/wsgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/public/hello.txt +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_analytics_engine.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_d1.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_do.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_images.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_kv.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_mtls.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_queue.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_r2.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_ratelimit.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_vectorize.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_version_metadata.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/test_workflow.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_durable_object.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/src/worker_workflow.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/bindings-test/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_bindings.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_fastapi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_flask.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/test_web_frameworks.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
- {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
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
- {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
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/src/test_response.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/web-frameworks-test/flask-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/asgi.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/tests/test_asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
- {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
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_litestar.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.js +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/sdk.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/server.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
- {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.
|
|
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
|
{workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.5}/src/_workers_sdk_entropy_import_context.py
RENAMED
|
@@ -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 == "
|
|
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
|
-
|
|
124
|
-
["npm", "i", "workerd"],
|
|
125
|
-
cwd=target,
|
|
126
|
-
check=True,
|
|
127
|
-
)
|
|
145
|
+
workerd_bin = resolve_workerd(target)
|
|
128
146
|
workerd_common = [
|
|
129
|
-
|
|
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
|
|
@@ -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,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")
|