workers-runtime-sdk 1.6.14__tar.gz → 1.7.0__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.6.14 → workers_runtime_sdk-1.7.0}/CHANGELOG.md +21 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/pyproject.toml +1 -1
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/asgi.py +36 -9
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/request.py +9 -3
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/response.py +2 -19
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/utils.py +20 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/_client.py +17 -0
- workers_runtime_sdk-1.7.0/tests/web-frameworks-test/fastapi-tests/src/test_platform_io.py +31 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +9 -0
- workers_runtime_sdk-1.7.0/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +39 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/worker.py +65 -46
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +19 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi-ws-disconnect/worker.py +43 -1
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/tests/test_sdk.py +5 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/uv.lock +1 -1
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/.gitignore +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/AGENTS.md +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/README.md +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_entropy_import_context.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_package_patches.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_patch_loader.pth +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_patch_loader.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/asgi.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/entrypoints.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/workers/wsgi.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/public/data.json +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/public/hello.txt +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/conftest.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_analytics_engine.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_d1.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_do.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_hyperdrive_mysql.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_hyperdrive_postgresql.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_images.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_kv.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_mtls.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_queue.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_r2.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_ratelimit.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_vectorize.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_version_metadata.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/test_workflow.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/worker_durable_object.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/src/worker_workflow.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/conftest.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/test_bindings.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/test_fastapi.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/test_in_workerd.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/test_web_frameworks.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi/asgi.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi/tests/test_asgi.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-abort/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/python-rpc/worker.js +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/python-rpc/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/sdk.wd-test +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/server.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/wsgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/wsgi/worker.py +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.7.0 (2026-08-24)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Fixes Request body being released too early
|
|
10
|
+
([`84a20ac`](https://github.com/cloudflare/workers-py/commit/84a20acbfa28ea82fb69b2c279a56d9e25fd9639))
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- Asgi.entrypoint syntax sugar for nicer asgi apps
|
|
15
|
+
([`5399270`](https://github.com/cloudflare/workers-py/commit/539927085a79e2d88a287cc70ccfa433ec257e1d))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## v1.6.15 (2026-08-21)
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
- Handle ASGI WebSocket close events and environment propagation
|
|
23
|
+
([`47cc488`](https://github.com/cloudflare/workers-py/commit/47cc488e2bad1c9f3030a16d73301b80fca90f5c))
|
|
24
|
+
|
|
25
|
+
|
|
5
26
|
## v1.6.14 (2026-08-19)
|
|
6
27
|
|
|
7
28
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: workers-runtime-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
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
|
|
@@ -7,7 +7,7 @@ from urllib.parse import unquote
|
|
|
7
7
|
|
|
8
8
|
import js
|
|
9
9
|
|
|
10
|
-
from workers import Context, Request
|
|
10
|
+
from workers import Context, Request, WorkerEntrypoint
|
|
11
11
|
from workers.utils import _to_js_headers
|
|
12
12
|
|
|
13
13
|
ASGI = {"spec_version": "2.0", "version": "3.0"}
|
|
@@ -317,7 +317,9 @@ async def process_request( # noqa: PLR0913
|
|
|
317
317
|
app_task.destroy()
|
|
318
318
|
|
|
319
319
|
|
|
320
|
-
async def process_websocket(
|
|
320
|
+
async def process_websocket(
|
|
321
|
+
app: Any, req: "Request | js.Request", env: Any = None
|
|
322
|
+
) -> js.Response:
|
|
321
323
|
from js import Response, WebSocketPair
|
|
322
324
|
|
|
323
325
|
client, server = WebSocketPair.new().object_values()
|
|
@@ -358,6 +360,10 @@ async def process_websocket(app: Any, req: "Request | js.Request") -> js.Respons
|
|
|
358
360
|
server.onmessage = onmessage
|
|
359
361
|
|
|
360
362
|
async def ws_send(got):
|
|
363
|
+
if got["type"] == "websocket.accept":
|
|
364
|
+
# The Workers WebSocketPair is accepted before the upgrade response
|
|
365
|
+
# is returned, so there is no deferred accept operation here.
|
|
366
|
+
return
|
|
361
367
|
if got["type"] == "websocket.send":
|
|
362
368
|
b = got.get("bytes", None)
|
|
363
369
|
s = got.get("text", None)
|
|
@@ -368,16 +374,23 @@ async def process_websocket(app: Any, req: "Request | js.Request") -> js.Respons
|
|
|
368
374
|
server.send(jsbytes)
|
|
369
375
|
if s is not None:
|
|
370
376
|
server.send(s)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
377
|
+
return
|
|
378
|
+
if got["type"] == "websocket.close":
|
|
379
|
+
server.close(got.get("code", 1000), got.get("reason", ""))
|
|
380
|
+
return
|
|
381
|
+
logger.warning(" == Not implemented %s", got["type"])
|
|
374
382
|
|
|
375
383
|
async def ws_receive():
|
|
376
384
|
received = await queue.get()
|
|
377
385
|
return received
|
|
378
386
|
|
|
379
|
-
|
|
380
|
-
|
|
387
|
+
run_in_background(
|
|
388
|
+
app(
|
|
389
|
+
request_to_scope(req, env if env is not None else {}, ws=True),
|
|
390
|
+
ws_receive,
|
|
391
|
+
ws_send,
|
|
392
|
+
)
|
|
393
|
+
)
|
|
381
394
|
|
|
382
395
|
return Response.new(None, status=101, webSocket=client)
|
|
383
396
|
|
|
@@ -396,8 +409,22 @@ async def fetch(
|
|
|
396
409
|
return result
|
|
397
410
|
|
|
398
411
|
|
|
399
|
-
async def websocket(
|
|
400
|
-
|
|
412
|
+
async def websocket(
|
|
413
|
+
app: Any, req: "Request | js.Request", env: Any = None
|
|
414
|
+
) -> js.Response:
|
|
415
|
+
return await process_websocket(app, req, env)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def entrypoint(app: Any) -> type[WorkerEntrypoint]:
|
|
419
|
+
"""Create the default Worker entrypoint for an ASGI application."""
|
|
420
|
+
|
|
421
|
+
class Default(WorkerEntrypoint):
|
|
422
|
+
async def fetch(self, request):
|
|
423
|
+
if (request.headers.get("upgrade") or "").lower() == "websocket":
|
|
424
|
+
return await websocket(app, request, self.env)
|
|
425
|
+
return await fetch(app, request, self.env, self.ctx)
|
|
426
|
+
|
|
427
|
+
return Default
|
|
401
428
|
|
|
402
429
|
|
|
403
430
|
def __getattr__(name):
|
|
@@ -9,6 +9,7 @@ from .blob import Blob
|
|
|
9
9
|
from .formdata import FormData
|
|
10
10
|
from .types import FetchKwargs
|
|
11
11
|
from .utils import (
|
|
12
|
+
_get_js_body,
|
|
12
13
|
_is_js_instance,
|
|
13
14
|
_js_headers_to_http_message,
|
|
14
15
|
_jsnull_to_none,
|
|
@@ -36,9 +37,14 @@ class Request:
|
|
|
36
37
|
|
|
37
38
|
if "headers" in other_options:
|
|
38
39
|
other_options["headers"] = _to_js_headers(other_options["headers"])
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
body = other_options.pop("body", None)
|
|
41
|
+
with _get_js_body(body) as js_body:
|
|
42
|
+
if body is not None:
|
|
43
|
+
other_options["body"] = js_body
|
|
44
|
+
self._js_request = js.Request.new(
|
|
45
|
+
input._js_request if isinstance(input, Request) else input,
|
|
46
|
+
**other_options,
|
|
47
|
+
)
|
|
42
48
|
|
|
43
49
|
def __repr__(self):
|
|
44
50
|
return (
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from contextlib import contextmanager
|
|
3
2
|
from http import HTTPStatus
|
|
4
3
|
from typing import Any, Never
|
|
5
4
|
|
|
6
5
|
import js
|
|
7
6
|
import pyodide.http
|
|
8
|
-
from pyodide.ffi import JsException, JsProxy
|
|
7
|
+
from pyodide.ffi import JsException, JsProxy
|
|
9
8
|
|
|
10
9
|
from .blob import Blob
|
|
11
10
|
from .formdata import FormData
|
|
12
11
|
from .types import Body, Headers
|
|
13
12
|
from .utils import (
|
|
14
13
|
RESPONSE_ACCEPTED_TYPES,
|
|
14
|
+
_get_js_body,
|
|
15
15
|
_get_js_constructor_name,
|
|
16
16
|
_is_js_instance,
|
|
17
17
|
_js_headers_to_http_message,
|
|
@@ -21,23 +21,6 @@ from .utils import (
|
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
@contextmanager
|
|
25
|
-
def _get_js_body(body):
|
|
26
|
-
if isinstance(body, bytes):
|
|
27
|
-
proxy_bytes = create_proxy(body)
|
|
28
|
-
proxy_buffer = proxy_bytes.getBuffer()
|
|
29
|
-
try:
|
|
30
|
-
yield proxy_buffer.data
|
|
31
|
-
return
|
|
32
|
-
finally:
|
|
33
|
-
proxy_buffer.release()
|
|
34
|
-
proxy_bytes.destroy()
|
|
35
|
-
if isinstance(body, FormData):
|
|
36
|
-
yield body.js_object
|
|
37
|
-
return
|
|
38
|
-
yield body
|
|
39
|
-
|
|
40
|
-
|
|
41
24
|
class FetchResponse(pyodide.http.FetchResponse):
|
|
42
25
|
# TODO: Consider upstreaming the `body` attribute
|
|
43
26
|
# TODO: Behind a compat flag make this return a native stream (StreamReader?), or perhaps
|
|
@@ -6,6 +6,7 @@ import _pyodide_entrypoint_helper
|
|
|
6
6
|
import js
|
|
7
7
|
from pyodide.ffi import (
|
|
8
8
|
JsException,
|
|
9
|
+
create_proxy,
|
|
9
10
|
destroy_proxies,
|
|
10
11
|
to_js,
|
|
11
12
|
)
|
|
@@ -51,6 +52,25 @@ _JS_PASSTHROUGH_TYPES = RESPONSE_ACCEPTED_TYPES | {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
|
|
55
|
+
@contextmanager
|
|
56
|
+
def _get_js_body(body):
|
|
57
|
+
from .formdata import FormData
|
|
58
|
+
|
|
59
|
+
if isinstance(body, bytes):
|
|
60
|
+
proxy_bytes = create_proxy(body)
|
|
61
|
+
proxy_buffer = proxy_bytes.getBuffer()
|
|
62
|
+
try:
|
|
63
|
+
yield proxy_buffer.data
|
|
64
|
+
return
|
|
65
|
+
finally:
|
|
66
|
+
proxy_buffer.release()
|
|
67
|
+
proxy_bytes.destroy()
|
|
68
|
+
if isinstance(body, FormData):
|
|
69
|
+
yield body.js_object
|
|
70
|
+
return
|
|
71
|
+
yield body
|
|
72
|
+
|
|
73
|
+
|
|
54
74
|
def _jsnull_to_none(x):
|
|
55
75
|
if x is jsnull:
|
|
56
76
|
return None
|
|
@@ -46,6 +46,23 @@ async def post_json(app, path, data, **kwargs):
|
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
def build_multipart_bytes(files, boundary="----WebTestBoundary"):
|
|
50
|
+
"""Build a binary-safe multipart body from (name, filename, bytes) tuples."""
|
|
51
|
+
body = bytearray()
|
|
52
|
+
for name, filename, content in files:
|
|
53
|
+
if isinstance(content, str):
|
|
54
|
+
content = content.encode()
|
|
55
|
+
body.extend(f"--{boundary}\r\n".encode())
|
|
56
|
+
body.extend(
|
|
57
|
+
f'Content-Disposition: form-data; name="{name}"; filename="{filename}"\r\n'.encode()
|
|
58
|
+
)
|
|
59
|
+
body.extend(b"Content-Type: application/octet-stream\r\n\r\n")
|
|
60
|
+
body.extend(content)
|
|
61
|
+
body.extend(b"\r\n")
|
|
62
|
+
body.extend(f"--{boundary}--\r\n".encode())
|
|
63
|
+
return bytes(body), f"multipart/form-data; boundary={boundary}"
|
|
64
|
+
|
|
65
|
+
|
|
49
66
|
def build_multipart(files, boundary="----WebTestBoundary"):
|
|
50
67
|
"""Build a multipart/form-data body from a list of (name, filename, content) tuples."""
|
|
51
68
|
lines = []
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Binary I/O tests across FastAPI, Pyodide, and workerd."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from _client import build_multipart_bytes, fetch, read_json
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.asyncio
|
|
10
|
+
async def test_upload_spills_binary_file_to_virtual_disk(fastapi_app):
|
|
11
|
+
"""UploadFile remains correct after SpooledTemporaryFile rolls to disk."""
|
|
12
|
+
payload = bytes(range(256)) * 5120 # 1.25 MiB, above Starlette's 1 MiB limit.
|
|
13
|
+
body, content_type = build_multipart_bytes(
|
|
14
|
+
[("file", "binary.dat", payload)], boundary="----SpoolBoundary"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
resp = await fetch(
|
|
18
|
+
fastapi_app,
|
|
19
|
+
"/platform/upload-spooled",
|
|
20
|
+
method="POST",
|
|
21
|
+
headers={"Content-Type": content_type},
|
|
22
|
+
body=body,
|
|
23
|
+
)
|
|
24
|
+
assert resp.status == 200
|
|
25
|
+
data = await read_json(resp)
|
|
26
|
+
assert data == {
|
|
27
|
+
"size": len(payload),
|
|
28
|
+
"sha256": hashlib.sha256(payload).hexdigest(),
|
|
29
|
+
"reread_matches": True,
|
|
30
|
+
"rolled_to_disk": True,
|
|
31
|
+
}
|
|
@@ -20,6 +20,15 @@ These are relevant for Pyodide/Workers because:
|
|
|
20
20
|
|
|
21
21
|
import pytest
|
|
22
22
|
from _client import fetch, get_json, read_json
|
|
23
|
+
from worker import Default
|
|
24
|
+
|
|
25
|
+
from workers import WorkerEntrypoint
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_asgi_entrypoint_factory():
|
|
29
|
+
assert Default.__name__ == "Default"
|
|
30
|
+
assert issubclass(Default, WorkerEntrypoint)
|
|
31
|
+
|
|
23
32
|
|
|
24
33
|
# -- Path parameters ---------------------------------------------------------
|
|
25
34
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from pyodide.ffi import create_proxy
|
|
5
|
+
from worker import Default
|
|
6
|
+
|
|
7
|
+
from workers import Request
|
|
8
|
+
|
|
9
|
+
TIMEOUT_S = 5
|
|
10
|
+
_proxies = []
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.asyncio
|
|
14
|
+
async def test_generated_entrypoint_serves_fastapi_websocket():
|
|
15
|
+
entrypoint = object.__new__(Default)
|
|
16
|
+
entrypoint.env = {}
|
|
17
|
+
request = Request(
|
|
18
|
+
"http://testserver/websocket/echo", headers={"Upgrade": "websocket"}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
response = await entrypoint.fetch(request)
|
|
22
|
+
assert response.status == 101
|
|
23
|
+
|
|
24
|
+
websocket = response.webSocket
|
|
25
|
+
websocket.accept()
|
|
26
|
+
message = asyncio.get_event_loop().create_future()
|
|
27
|
+
|
|
28
|
+
def onmessage(event):
|
|
29
|
+
if not message.done():
|
|
30
|
+
message.set_result(event.data)
|
|
31
|
+
|
|
32
|
+
proxy = create_proxy(onmessage)
|
|
33
|
+
_proxies.append(proxy)
|
|
34
|
+
websocket.addEventListener("message", proxy)
|
|
35
|
+
try:
|
|
36
|
+
websocket.send("hello")
|
|
37
|
+
assert await asyncio.wait_for(message, TIMEOUT_S) == "echo:hello"
|
|
38
|
+
finally:
|
|
39
|
+
websocket.close()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import enum
|
|
3
|
+
import hashlib
|
|
3
4
|
import importlib.util
|
|
4
5
|
from contextlib import asynccontextmanager
|
|
5
6
|
from pathlib import Path
|
|
@@ -15,6 +16,7 @@ from fastapi import (
|
|
|
15
16
|
Query,
|
|
16
17
|
Request,
|
|
17
18
|
UploadFile,
|
|
19
|
+
WebSocket,
|
|
18
20
|
)
|
|
19
21
|
from fastapi.exceptions import HTTPException
|
|
20
22
|
from fastapi.responses import (
|
|
@@ -32,7 +34,6 @@ from pyodide.webloop import WebLoop
|
|
|
32
34
|
from starlette.background import BackgroundTask
|
|
33
35
|
|
|
34
36
|
import asgi
|
|
35
|
-
from workers import Response, WorkerEntrypoint
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
async def _noop(*args):
|
|
@@ -82,6 +83,14 @@ async def health():
|
|
|
82
83
|
return {"ok": True}
|
|
83
84
|
|
|
84
85
|
|
|
86
|
+
@app.websocket("/websocket/echo")
|
|
87
|
+
async def websocket_echo(websocket: WebSocket):
|
|
88
|
+
await websocket.accept()
|
|
89
|
+
message = await websocket.receive_text()
|
|
90
|
+
await websocket.send_text(f"echo:{message}")
|
|
91
|
+
await websocket.close()
|
|
92
|
+
|
|
93
|
+
|
|
85
94
|
# -- sync route handler (dispatched via run_in_threadpool) -------------------
|
|
86
95
|
@app.get("/sync/hello")
|
|
87
96
|
def sync_hello():
|
|
@@ -436,6 +445,24 @@ async def platform_lifespan_state(request: Request):
|
|
|
436
445
|
return {"available": True, "closed": resource.closed}
|
|
437
446
|
|
|
438
447
|
|
|
448
|
+
# --------------------------------------------------------------------------- #
|
|
449
|
+
# Pyodide and Workers platform boundary routes
|
|
450
|
+
# --------------------------------------------------------------------------- #
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
@app.post("/platform/upload-spooled")
|
|
454
|
+
async def platform_upload_spooled(file: UploadFile = File(...)): # noqa: B008
|
|
455
|
+
first = await file.read()
|
|
456
|
+
await file.seek(0)
|
|
457
|
+
second = await file.read()
|
|
458
|
+
return {
|
|
459
|
+
"size": len(first),
|
|
460
|
+
"sha256": hashlib.sha256(first).hexdigest(),
|
|
461
|
+
"reread_matches": first == second,
|
|
462
|
+
"rolled_to_disk": bool(getattr(file.file, "_rolled", False)),
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
|
|
439
466
|
@app.get("/native-file")
|
|
440
467
|
async def native_file():
|
|
441
468
|
"""Serve a single bundled file with FastAPI's native FileResponse."""
|
|
@@ -447,17 +474,6 @@ async def native_file():
|
|
|
447
474
|
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
|
448
475
|
|
|
449
476
|
|
|
450
|
-
@app.get("/{path:path}")
|
|
451
|
-
async def frontend(path: str, request: Request):
|
|
452
|
-
"""Proxy static asset requests to the Workers Assets binding."""
|
|
453
|
-
env = request.scope["env"]
|
|
454
|
-
asset_url = f"https://assets.local/{path}"
|
|
455
|
-
resp = await env.ASSETS.fetch(asset_url)
|
|
456
|
-
body = await resp.bytes()
|
|
457
|
-
headers = dict(resp.headers)
|
|
458
|
-
return FastAPIResponse(content=body, status_code=resp.status, headers=headers)
|
|
459
|
-
|
|
460
|
-
|
|
461
477
|
class ResultCollector:
|
|
462
478
|
def __init__(self):
|
|
463
479
|
self.results = {}
|
|
@@ -524,37 +540,40 @@ class FastAPIAppPlugin:
|
|
|
524
540
|
return app
|
|
525
541
|
|
|
526
542
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
543
|
+
@app.get("/run-tests/{suite_name:path}")
|
|
544
|
+
async def run_suite(suite_name: str, request: Request):
|
|
545
|
+
module = f"test_{suite_name}"
|
|
546
|
+
if importlib.util.find_spec(module) is None:
|
|
547
|
+
return JSONResponse(
|
|
548
|
+
{"error": f"Unknown suite '{suite_name}' (no module '{module}')"},
|
|
549
|
+
status_code=404,
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
collector = ResultCollector()
|
|
553
|
+
saved_loop = asyncio.events._get_running_loop()
|
|
554
|
+
try:
|
|
555
|
+
pytest.main(
|
|
556
|
+
["--pyargs", module, "-p", "no:cacheprovider"],
|
|
557
|
+
plugins=[
|
|
558
|
+
collector,
|
|
559
|
+
EnvPlugin(request.scope["env"]),
|
|
560
|
+
FastAPIAppPlugin(),
|
|
561
|
+
],
|
|
562
|
+
)
|
|
563
|
+
finally:
|
|
564
|
+
asyncio.events._set_running_loop(saved_loop)
|
|
565
|
+
return collector.results
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
@app.get("/{path:path}")
|
|
569
|
+
async def frontend(path: str, request: Request):
|
|
570
|
+
"""Proxy static asset requests to the Workers Assets binding."""
|
|
571
|
+
env = request.scope["env"]
|
|
572
|
+
asset_url = f"https://assets.local/{path}"
|
|
573
|
+
resp = await env.ASSETS.fetch(asset_url)
|
|
574
|
+
body = await resp.bytes()
|
|
575
|
+
headers = dict(resp.headers)
|
|
576
|
+
return FastAPIResponse(content=body, status_code=resp.status, headers=headers)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
Default = asgi.entrypoint(app)
|
|
@@ -140,3 +140,22 @@ async def test_empty_frames_reach_the_client():
|
|
|
140
140
|
assert messages[0] == ""
|
|
141
141
|
assert messages[1].to_bytes() == b""
|
|
142
142
|
assert messages[2] == "done"
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@pytest.mark.asyncio
|
|
146
|
+
async def test_application_close_reaches_client_with_code_and_reason():
|
|
147
|
+
async with _ws_session("/ws-close") as ws:
|
|
148
|
+
closed = _listen(ws, "close")
|
|
149
|
+
ws.send("close")
|
|
150
|
+
event = await asyncio.wait_for(closed, TIMEOUT_S)
|
|
151
|
+
assert event.code == 4001
|
|
152
|
+
assert event.reason == "application-close"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@pytest.mark.asyncio
|
|
156
|
+
async def test_environment_reaches_websocket_scope():
|
|
157
|
+
async with _ws_session("/ws-env") as ws:
|
|
158
|
+
message = _listen(ws, "message")
|
|
159
|
+
ws.send("env")
|
|
160
|
+
event = await asyncio.wait_for(message, TIMEOUT_S)
|
|
161
|
+
assert event.data == "worker-environment"
|
|
@@ -101,16 +101,58 @@ class WSEmptyFrameApp:
|
|
|
101
101
|
await send({"type": "websocket.send", "text": "done"})
|
|
102
102
|
|
|
103
103
|
|
|
104
|
+
class WSCloseApp:
|
|
105
|
+
"""Closes the connection with an application-provided code and reason."""
|
|
106
|
+
|
|
107
|
+
async def __call__(self, scope, receive, send):
|
|
108
|
+
message = await receive()
|
|
109
|
+
assert message["type"] == "websocket.connect"
|
|
110
|
+
await send({"type": "websocket.accept"})
|
|
111
|
+
message = await receive()
|
|
112
|
+
if message["type"] == "websocket.disconnect":
|
|
113
|
+
return
|
|
114
|
+
await send(
|
|
115
|
+
{
|
|
116
|
+
"type": "websocket.close",
|
|
117
|
+
"code": 4001,
|
|
118
|
+
"reason": "application-close",
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class WSEnvApp:
|
|
124
|
+
"""Sends a value supplied through the ASGI WebSocket scope environment."""
|
|
125
|
+
|
|
126
|
+
async def __call__(self, scope, receive, send):
|
|
127
|
+
message = await receive()
|
|
128
|
+
assert message["type"] == "websocket.connect"
|
|
129
|
+
await send({"type": "websocket.accept"})
|
|
130
|
+
message = await receive()
|
|
131
|
+
if message["type"] == "websocket.disconnect":
|
|
132
|
+
return
|
|
133
|
+
await send({"type": "websocket.send", "text": scope["env"]["marker"]})
|
|
134
|
+
|
|
135
|
+
|
|
104
136
|
ws_app = WSWatchApp()
|
|
105
137
|
echo_app = WSEchoApp()
|
|
106
138
|
empty_frame_app = WSEmptyFrameApp()
|
|
139
|
+
close_app = WSCloseApp()
|
|
140
|
+
env_app = WSEnvApp()
|
|
107
141
|
|
|
108
142
|
|
|
109
143
|
class Default(WorkerEntrypoint):
|
|
110
144
|
async def fetch(self, request):
|
|
111
145
|
if (request.headers.get("upgrade") or "").lower() == "websocket":
|
|
112
146
|
path = urlsplit(request.url).path
|
|
113
|
-
|
|
147
|
+
if path == "/ws-env":
|
|
148
|
+
return await asgi.websocket(
|
|
149
|
+
env_app, request, {"marker": "worker-environment"}
|
|
150
|
+
)
|
|
151
|
+
app = {
|
|
152
|
+
"/ws-close": close_app,
|
|
153
|
+
"/ws-echo": echo_app,
|
|
154
|
+
"/ws-empty": empty_frame_app,
|
|
155
|
+
}.get(path, ws_app)
|
|
114
156
|
return await asgi.websocket(app, request)
|
|
115
157
|
import json
|
|
116
158
|
|
{workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/workerd-test/sdk/tests/test_sdk.py
RENAMED
|
@@ -436,6 +436,11 @@ async def test_request_unit_tests():
|
|
|
436
436
|
blob = await req_for_blob.blob()
|
|
437
437
|
assert (await blob.text()) == "foobar"
|
|
438
438
|
|
|
439
|
+
# Verify that Python bytes are converted without UTF-8 decoding or truncation.
|
|
440
|
+
binary_body = bytes(range(256))
|
|
441
|
+
req_for_bytes = Request("http://example.com", body=binary_body, method="POST")
|
|
442
|
+
assert await req_for_bytes.bytes() == binary_body
|
|
443
|
+
|
|
439
444
|
# Verify that we can get a FormData back.
|
|
440
445
|
js_form_data = js.FormData.new()
|
|
441
446
|
js_form_data.append("foobar", 123)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_entropy_import_context.py
RENAMED
|
File without changes
|
{workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/src/_workers_sdk_package_patches.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workers_runtime_sdk-1.6.14 → workers_runtime_sdk-1.7.0}/tests/bindings-test/public/data.json
RENAMED
|
File without changes
|