workers-runtime-sdk 1.8.2__tar.gz → 1.8.4__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.2 → workers_runtime_sdk-1.8.4}/CHANGELOG.md +18 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/pyproject.toml +6 -30
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_workers_sdk_entropy_import_context.py +11 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/asgi.py +12 -3
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/pyproject.toml +4 -1
- workers_runtime_sdk-1.8.4/tests/bindings-test/src/worker.py +32 -0
- workers_runtime_sdk-1.8.4/tests/conftest.py +116 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/test_fastapi.py +1 -5
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/test_in_workerd.py +11 -7
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/pyproject.toml +4 -0
- workers_runtime_sdk-1.8.4/tests/web-frameworks-test/django-async/src/worker.py +104 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +4 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/worker.py +4 -73
- workers_runtime_sdk-1.8.4/tests/web-frameworks-test/flask-tests/pyproject.toml +8 -0
- workers_runtime_sdk-1.8.4/tests/web-frameworks-test/flask-tests/src/worker.py +5 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/tests/test_asgi.py +46 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +11 -14
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/pyproject.toml +4 -1
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -1
- workers_runtime_sdk-1.8.2/tests/workerd-test/entropy-patches/tests/test_rust_packages.py → workers_runtime_sdk-1.8.4/tests/workerd-test/entropy-patches/tests/test_litestar.py +1 -4
- workers_runtime_sdk-1.8.4/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +19 -0
- workers_runtime_sdk-1.8.4/tests/workerd-test/entropy-patches/worker.py +17 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/uv.lock +23 -1
- workers_runtime_sdk-1.8.2/tests/bindings-test/src/worker.py +0 -186
- workers_runtime_sdk-1.8.2/tests/conftest.py +0 -290
- workers_runtime_sdk-1.8.2/tests/web-frameworks-test/django-async/src/worker.py +0 -206
- workers_runtime_sdk-1.8.2/tests/web-frameworks-test/flask-tests/pyproject.toml +0 -5
- workers_runtime_sdk-1.8.2/tests/web-frameworks-test/flask-tests/src/worker.py +0 -89
- workers_runtime_sdk-1.8.2/tests/workerd-test/entropy-patches/worker.py +0 -27
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/.gitignore +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/AGENTS.md +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/README.md +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_workers_sdk_package_patches.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_workers_sdk_patch_loader.pth +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_workers_sdk_patch_loader.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/asgi.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/entrypoints.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/request.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/response.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/utils.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/workers/wsgi.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/public/data.json +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/public/hello.txt +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_analytics_engine.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_d1.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_do.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_hyperdrive_mysql.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_hyperdrive_postgresql.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_images.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_kv.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_mtls.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_queue.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_r2.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_ratelimit.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_vectorize.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_version_metadata.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/test_workflow.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/worker_durable_object.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/src/worker_workflow.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/bindings-test/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/test_bindings.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/test_flask.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/test_web_frameworks.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_platform_boundaries.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_platform_io.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/flask-tests/src/test_response.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/web-frameworks-test/flask-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/asgi.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-abort/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/python-rpc/worker.js +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/python-rpc/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/sdk.wd-test +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/server.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/wsgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/wsgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.8.4 (2026-09-08)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **runtime-sdk**: Fix top-level entropy call for litestar and fix entropy tests
|
|
10
|
+
([#241](https://github.com/cloudflare/workers-py/pull/241),
|
|
11
|
+
[`99b77c7`](https://github.com/cloudflare/workers-py/commit/99b77c7658d1e4b0591233b8ce6cc179719751e3))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## v1.8.3 (2026-08-31)
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
- **runtime-sdk**: Stop losing details of ASGI lifespan failures
|
|
19
|
+
([#172](https://github.com/cloudflare/workers-py/pull/172),
|
|
20
|
+
[`c6d1f69`](https://github.com/cloudflare/workers-py/commit/c6d1f69e96fd13b5b9e41f48e70aebb7469310c8))
|
|
21
|
+
|
|
22
|
+
|
|
5
23
|
## v1.8.2 (2026-08-31)
|
|
6
24
|
|
|
7
25
|
### 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.4
|
|
4
4
|
Summary: Python SDK for Cloudflare Workers
|
|
5
5
|
Project-URL: Homepage, https://github.com/cloudflare/workers-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/cloudflare/workers-py/issues
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "workers-runtime-sdk"
|
|
7
|
-
version = "1.8.
|
|
7
|
+
version = "1.8.4"
|
|
8
8
|
description = "Python SDK for Cloudflare Workers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -21,42 +21,18 @@ dev = [
|
|
|
21
21
|
"ruff>=0.1.0",
|
|
22
22
|
"mypy>=1.0.0",
|
|
23
23
|
"requests>=2.28.0",
|
|
24
|
+
"testlib[host]",
|
|
24
25
|
]
|
|
25
26
|
|
|
27
|
+
[tool.uv.sources]
|
|
28
|
+
testlib = { path = "../testlib", editable = true }
|
|
29
|
+
|
|
26
30
|
[project.urls]
|
|
27
31
|
"Homepage" = "https://github.com/cloudflare/workers-py"
|
|
28
32
|
"Bug Tracker" = "https://github.com/cloudflare/workers-py/issues"
|
|
29
33
|
|
|
30
34
|
[tool.ruff]
|
|
31
|
-
|
|
32
|
-
lint.select = [
|
|
33
|
-
"B0", # bugbear (all B0* checks enabled by default)
|
|
34
|
-
"B904", # bugbear (Within an except clause, raise exceptions with raise ... from err)
|
|
35
|
-
"B905", # bugbear (zip() without an explicit strict= parameter set.)
|
|
36
|
-
"C4", # flake8-comprehensions
|
|
37
|
-
"C9", # mccabe complexity
|
|
38
|
-
"E", # pycodestyles
|
|
39
|
-
"F", # pyflakes
|
|
40
|
-
"I", # isort
|
|
41
|
-
"PERF", # Perflint
|
|
42
|
-
"PGH", # pygrep-hooks
|
|
43
|
-
"PL", # Pylint
|
|
44
|
-
"UP", # pyupgrade
|
|
45
|
-
"W", # pycodestyles
|
|
46
|
-
]
|
|
47
|
-
lint.ignore = [
|
|
48
|
-
"C901", # Too complex
|
|
49
|
-
"E402",
|
|
50
|
-
"E501",
|
|
51
|
-
"E731",
|
|
52
|
-
"E741",
|
|
53
|
-
"PLR0911", # Too many return statements
|
|
54
|
-
"PLR0915", # Too many statements
|
|
55
|
-
"PLW2901",
|
|
56
|
-
"UP031",
|
|
57
|
-
"UP038", # Use X | Y instead of (X, Y)
|
|
58
|
-
]
|
|
59
|
-
lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments = true
|
|
35
|
+
extend = "../../ruff.toml"
|
|
60
36
|
lint.per-file-ignores."tests/**" = ["PLR2004", "PLR0913"]
|
|
61
37
|
lint.per-file-ignores."tests/workerd-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
|
|
62
38
|
lint.per-file-ignores."tests/bindings-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
|
{workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/src/_workers_sdk_entropy_import_context.py
RENAMED
|
@@ -178,3 +178,14 @@ def langsmith__internal__constants_context(module):
|
|
|
178
178
|
def langchain_openai_chat_models_base_context(module):
|
|
179
179
|
with allow_bad_entropy_calls(1):
|
|
180
180
|
yield
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@register_exec_patch("litestar.openapi.controller")
|
|
184
|
+
@register_exec_patch("litestar.constants")
|
|
185
|
+
@contextmanager
|
|
186
|
+
def litestar_context(module):
|
|
187
|
+
# Uses os.urandom() to generate a OPENAPI_JSON_HANDLER_NAME
|
|
188
|
+
# https://github.com/litestar-org/litestar/blob/e3b6a1d103a9160a575dce01ae34839e6e9bf990/litestar/constants.py#L19
|
|
189
|
+
# https://github.com/litestar-org/litestar/blob/v2.24.0/litestar/openapi/controller.py#L27
|
|
190
|
+
with allow_bad_entropy_calls(1):
|
|
191
|
+
yield
|
|
@@ -127,7 +127,9 @@ async def start_application(app):
|
|
|
127
127
|
startup.set_result(True)
|
|
128
128
|
return
|
|
129
129
|
if got["type"] == "lifespan.startup.failed":
|
|
130
|
-
|
|
130
|
+
# `or`, not a .get default: an empty message field is legal and
|
|
131
|
+
# would otherwise produce RuntimeError('').
|
|
132
|
+
message = got.get("message") or "ASGI lifespan startup failed"
|
|
131
133
|
if not startup.done():
|
|
132
134
|
startup.set_exception(RuntimeError(message))
|
|
133
135
|
return
|
|
@@ -136,7 +138,7 @@ async def start_application(app):
|
|
|
136
138
|
shutdown_complete.set_result(None)
|
|
137
139
|
return
|
|
138
140
|
if got["type"] == "lifespan.shutdown.failed":
|
|
139
|
-
message = got.get("message"
|
|
141
|
+
message = got.get("message") or "ASGI lifespan shutdown failed"
|
|
140
142
|
if not shutdown_complete.done():
|
|
141
143
|
shutdown_complete.set_exception(RuntimeError(message))
|
|
142
144
|
return
|
|
@@ -161,8 +163,15 @@ async def start_application(app):
|
|
|
161
163
|
shutdown_complete.set_result(None)
|
|
162
164
|
except Exception as exc:
|
|
163
165
|
# Spec: an exception raised before startup is acked signals that the
|
|
164
|
-
# app doesn't support lifespan;
|
|
166
|
+
# app doesn't support lifespan; serve requests anyway. Log it, or an
|
|
167
|
+
# app that crashed mid-startup looks like one with no lifespan
|
|
168
|
+
# handler at all.
|
|
165
169
|
if not startup.done():
|
|
170
|
+
logger.debug(
|
|
171
|
+
"ASGI lifespan task raised before reporting startup; "
|
|
172
|
+
"treating the app as not supporting lifespan",
|
|
173
|
+
exc_info=exc,
|
|
174
|
+
)
|
|
166
175
|
startup.set_result(False)
|
|
167
176
|
return
|
|
168
177
|
# After a successful startup, a shutdown-phase error can't affect the
|
|
@@ -2,4 +2,7 @@
|
|
|
2
2
|
name = "bindings-test"
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
requires-python = ">=3.12"
|
|
5
|
-
dependencies = ["pytest", "pytest-asyncio<1.2.0", "pg8000", "pymysql", "cryptography"]
|
|
5
|
+
dependencies = ["pytest", "pytest-asyncio<1.2.0", "pg8000", "pymysql", "cryptography", "testlib"]
|
|
6
|
+
|
|
7
|
+
[tool.uv.sources]
|
|
8
|
+
testlib = { path = "../testlib/dist/testlib-0.0.0-py3-none-any.whl" }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Bindings test worker.
|
|
2
|
+
|
|
3
|
+
Each binding suite lives in a `test_<suite>.py` module written as ordinary pytest
|
|
4
|
+
tests (see test_kv.py). The `/run-tests/<suite>` endpoint runs pytest against that
|
|
5
|
+
module inside workerd and returns per-test results as JSON, which the host-side
|
|
6
|
+
test_bindings.py maps onto individual pytest cases.
|
|
7
|
+
|
|
8
|
+
To add a new binding: create `src/test_<binding>.py` with pytest tests.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from testlib.entrypoint import TestRunnerEntrypoint
|
|
12
|
+
from worker_durable_object import (
|
|
13
|
+
TestDurableObject, # noqa: F401 - import to trigger side effect of registering the Durable Object
|
|
14
|
+
)
|
|
15
|
+
from worker_workflow import (
|
|
16
|
+
TestWorkflow, # noqa: F401 - import to trigger side effect of registering the Workflow
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
RECEIVED_MESSAGES = []
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Default(TestRunnerEntrypoint):
|
|
23
|
+
async def queue(self, batch, env, ctx):
|
|
24
|
+
for message in batch.messages:
|
|
25
|
+
RECEIVED_MESSAGES.append(
|
|
26
|
+
{
|
|
27
|
+
"id": message.id,
|
|
28
|
+
"body": message.body,
|
|
29
|
+
"attempts": message.attempts,
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
message.ack()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Shared fixtures and helpers for the host-side test suite."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
from collections.abc import Generator
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
from testlib.host import (
|
|
12
|
+
COMPAT_CONFIGS,
|
|
13
|
+
CompatConfig,
|
|
14
|
+
configure_compatibility,
|
|
15
|
+
)
|
|
16
|
+
from testlib.host import (
|
|
17
|
+
dev_server as run_dev_server,
|
|
18
|
+
)
|
|
19
|
+
from testlib.host import (
|
|
20
|
+
register_in_worker_suites as register_testlib_suites,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
TEST_DIR: Path = Path(__file__).parent
|
|
24
|
+
WORKERS_PY: Path = TEST_DIR.parent.parent / "cli"
|
|
25
|
+
WORKERS_RUNTIME_SDK: Path = TEST_DIR.parent / "src"
|
|
26
|
+
TESTLIB: Path = TEST_DIR.parent.parent / "testlib"
|
|
27
|
+
|
|
28
|
+
DEV_STARTUP_TIMEOUT: int = 120
|
|
29
|
+
OPT_IN_MARKERS: tuple[str, ...] = ("hyperdrive",)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def pytest_collection_modifyitems(
|
|
33
|
+
config: pytest.Config, items: list[pytest.Item]
|
|
34
|
+
) -> None:
|
|
35
|
+
"""Skip opt-in suites unless the run explicitly asks for them via ``-m``."""
|
|
36
|
+
markexpr: str = config.getoption("markexpr")
|
|
37
|
+
for marker in OPT_IN_MARKERS:
|
|
38
|
+
if marker in markexpr:
|
|
39
|
+
continue
|
|
40
|
+
skip = pytest.mark.skip(reason=f"needs local services; run with -m {marker}")
|
|
41
|
+
for item in items:
|
|
42
|
+
if marker in item.keywords:
|
|
43
|
+
item.add_marker(skip)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.fixture(scope="session", autouse=True)
|
|
47
|
+
def build_testlib():
|
|
48
|
+
subprocess.run(["uv", "build"], cwd=TESTLIB, check=True)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.fixture(
|
|
52
|
+
scope="module",
|
|
53
|
+
params=COMPAT_CONFIGS,
|
|
54
|
+
ids=[c.python_version for c in COMPAT_CONFIGS],
|
|
55
|
+
)
|
|
56
|
+
def compat_config(request: pytest.FixtureRequest) -> CompatConfig:
|
|
57
|
+
return request.param
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@pytest.fixture(scope="module")
|
|
61
|
+
def worker_project_dir() -> Path:
|
|
62
|
+
"""Worker project the `dev_server` fixture should serve.
|
|
63
|
+
|
|
64
|
+
Test modules using `dev_server` must override this fixture.
|
|
65
|
+
"""
|
|
66
|
+
raise NotImplementedError(
|
|
67
|
+
"override the `worker_project_dir` fixture in your test module"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.fixture(scope="module")
|
|
72
|
+
def dev_server(
|
|
73
|
+
tmp_path_factory: pytest.TempPathFactory,
|
|
74
|
+
worker_project_dir: Path,
|
|
75
|
+
compat_config: CompatConfig,
|
|
76
|
+
) -> Generator[str]:
|
|
77
|
+
"""Start a pywrangler dev server on a free port and yield its base URL."""
|
|
78
|
+
tmp_path = tmp_path_factory.mktemp(f"{worker_project_dir.name}_dev")
|
|
79
|
+
target = tmp_path / worker_project_dir.name
|
|
80
|
+
shutil.copytree(worker_project_dir, target, ignore=shutil.ignore_patterns(".venv"))
|
|
81
|
+
shutil.copytree(TESTLIB, tmp_path / "testlib")
|
|
82
|
+
env = os.environ | {"_PYODIDE_EXTRA_MOUNTS": str(tmp_path)}
|
|
83
|
+
|
|
84
|
+
wrangler_jsonc = target / "wrangler.jsonc"
|
|
85
|
+
configure_compatibility(wrangler_jsonc, compat_config)
|
|
86
|
+
|
|
87
|
+
pywrangler_cmd = ["uv", "run", "--no-project", "--with", WORKERS_PY, "pywrangler"]
|
|
88
|
+
|
|
89
|
+
subprocess.run(
|
|
90
|
+
[*pywrangler_cmd, "sync"],
|
|
91
|
+
cwd=target,
|
|
92
|
+
check=True,
|
|
93
|
+
env=env,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
shutil.copytree(WORKERS_RUNTIME_SDK, target / "python_modules", dirs_exist_ok=True)
|
|
97
|
+
|
|
98
|
+
with run_dev_server(
|
|
99
|
+
target,
|
|
100
|
+
tmp_path,
|
|
101
|
+
env,
|
|
102
|
+
pywrangler_cmd,
|
|
103
|
+
startup_timeout=DEV_STARTUP_TIMEOUT,
|
|
104
|
+
readiness_path="/health",
|
|
105
|
+
require_success=True,
|
|
106
|
+
log_name="dev.log",
|
|
107
|
+
) as (base_url, _):
|
|
108
|
+
yield base_url
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def register_in_worker_suites(
|
|
112
|
+
namespace: dict[str, Any],
|
|
113
|
+
src_dir: Path,
|
|
114
|
+
marks: dict[str, pytest.MarkDecorator] | None = None,
|
|
115
|
+
) -> None:
|
|
116
|
+
register_testlib_suites(namespace, src_dir, marks=marks, class_name=str.upper)
|
|
@@ -4,9 +4,6 @@ Python 3.12 (Pyodide 0.26.0a2) is excluded. The in-worker pytest suite drives
|
|
|
4
4
|
async tests via ``loop.run_until_complete``, which is a no-op on Pyodide 0.26.0a2
|
|
5
5
|
(no ``run_sync``/JSPI): async tests return unawaited futures and report false
|
|
6
6
|
passes.
|
|
7
|
-
|
|
8
|
-
Python 3.14 is excluded because pydantic_core has a circular import error on
|
|
9
|
-
the 3.14 Pyodide runtime (``validate_core_schema`` not found during module init).
|
|
10
7
|
"""
|
|
11
8
|
|
|
12
9
|
from pathlib import Path
|
|
@@ -26,9 +23,8 @@ def worker_project_dir() -> Path:
|
|
|
26
23
|
|
|
27
24
|
|
|
28
25
|
# Exclude Python 3.12 (Pyodide 0.26.0a2) for async tests.
|
|
29
|
-
# Exclude Python 3.14 due to pydantic_core circular import error on Pyodide.
|
|
30
26
|
FASTAPI_COMPAT_CONFIGS = [
|
|
31
|
-
c for c in COMPAT_CONFIGS if c.python_version not in ("3.12",
|
|
27
|
+
c for c in COMPAT_CONFIGS if c.python_version not in ("3.12",)
|
|
32
28
|
]
|
|
33
29
|
|
|
34
30
|
|
|
@@ -7,8 +7,7 @@ import pytest
|
|
|
7
7
|
from conftest import (
|
|
8
8
|
COMPAT_CONFIGS,
|
|
9
9
|
CompatConfig,
|
|
10
|
-
|
|
11
|
-
replace_compat_date,
|
|
10
|
+
configure_compatibility,
|
|
12
11
|
)
|
|
13
12
|
|
|
14
13
|
TEST_DIR = Path(__file__).parent
|
|
@@ -62,7 +61,7 @@ def bundle_cache_dir(tmp_path_factory):
|
|
|
62
61
|
ids=[c.python_version for c in COMPAT_CONFIGS],
|
|
63
62
|
)
|
|
64
63
|
@pytest.mark.parametrize("test_dir, wd_test_file", discover_workerd_tests())
|
|
65
|
-
def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
|
|
64
|
+
def test_in_workerd( # noqa: PLR0913, PLR0917 (too-many-arguments)
|
|
66
65
|
tmp_path,
|
|
67
66
|
test_dir,
|
|
68
67
|
wd_test_file,
|
|
@@ -71,22 +70,27 @@ def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
|
|
|
71
70
|
bundle_cache_dir,
|
|
72
71
|
):
|
|
73
72
|
compat_date = compat_config.compat_date
|
|
73
|
+
python_version = compat_config.python_version
|
|
74
74
|
|
|
75
75
|
# `wsgi` streams the request body via `pyodide.ffi.run_sync` (JSPI), which
|
|
76
76
|
# is only available in newer Pyodide runtimes.
|
|
77
|
-
if test_dir.name == "wsgi" and
|
|
77
|
+
if test_dir.name == "wsgi" and python_version == "3.12":
|
|
78
78
|
pytest.skip(
|
|
79
79
|
"wsgi requires pyodide.ffi.run_sync (JSPI), unavailable before 2026-01-01"
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
+
if test_dir.name == "entropy-patches" and python_version == "3.14":
|
|
83
|
+
pytest.skip(
|
|
84
|
+
"TODO: enable me after https://github.com/cloudflare/workerd/pull/7200 lands in wrangler"
|
|
85
|
+
)
|
|
86
|
+
|
|
82
87
|
color = pytestconfig.get_terminal_writer().hasmarkup
|
|
83
88
|
target = tmp_path / test_dir.name
|
|
84
89
|
disk_service_dir = target / DISK_SERVICE_NAME
|
|
85
90
|
shutil.copytree(test_dir, target, ignore=shutil.ignore_patterns(".venv"))
|
|
86
91
|
disk_service_dir.mkdir(exist_ok=True)
|
|
87
92
|
|
|
88
|
-
|
|
89
|
-
inject_compat_flags(target / "wrangler.jsonc", compat_config.extra_compat_flags)
|
|
93
|
+
configure_compatibility(target / "wrangler.jsonc", compat_config)
|
|
90
94
|
|
|
91
95
|
pywrangler_cmd = ["uv", "run", "--no-project", "--with", WORKERS_PY, "pywrangler"]
|
|
92
96
|
|
|
@@ -114,7 +118,7 @@ def test_in_workerd( # noqa: PLR0913 (too-many-arguments)
|
|
|
114
118
|
.replace("%COLOR", str(color).lower())
|
|
115
119
|
.replace("%COMPAT_DATE", compat_date)
|
|
116
120
|
)
|
|
117
|
-
|
|
121
|
+
configure_compatibility(wd_config, compat_config)
|
|
118
122
|
|
|
119
123
|
subprocess.run(
|
|
120
124
|
["npm", "i", "workerd"],
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from testlib.entrypoint import TestRunnerEntrypoint
|
|
5
|
+
|
|
6
|
+
import asgi
|
|
7
|
+
|
|
8
|
+
BASE_DIR = Path(__file__).parent
|
|
9
|
+
TEMPLATES_DIR = str(BASE_DIR / "templates")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import django.conf # noqa: E402
|
|
13
|
+
|
|
14
|
+
django.conf.settings.configure(
|
|
15
|
+
DEBUG=False,
|
|
16
|
+
SECRET_KEY="test-secret-key-for-workers-py",
|
|
17
|
+
ROOT_URLCONF="django_app.urls",
|
|
18
|
+
ALLOWED_HOSTS=["*"],
|
|
19
|
+
INSTALLED_APPS=[
|
|
20
|
+
"django.contrib.contenttypes",
|
|
21
|
+
"django.contrib.sessions",
|
|
22
|
+
"django.contrib.auth",
|
|
23
|
+
"rest_framework",
|
|
24
|
+
"corsheaders",
|
|
25
|
+
],
|
|
26
|
+
MIDDLEWARE=[
|
|
27
|
+
"corsheaders.middleware.CorsMiddleware",
|
|
28
|
+
"django.middleware.security.SecurityMiddleware",
|
|
29
|
+
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
30
|
+
"django.middleware.common.CommonMiddleware",
|
|
31
|
+
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
32
|
+
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
33
|
+
"django_app.middleware.CustomAsyncMiddleware",
|
|
34
|
+
],
|
|
35
|
+
TEMPLATES=[
|
|
36
|
+
{
|
|
37
|
+
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
38
|
+
"DIRS": [TEMPLATES_DIR],
|
|
39
|
+
"APP_DIRS": False,
|
|
40
|
+
"OPTIONS": {
|
|
41
|
+
"context_processors": [
|
|
42
|
+
"django.template.context_processors.request",
|
|
43
|
+
],
|
|
44
|
+
"builtins": ["django_app.templatetags.custom_tags"],
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
CACHES={
|
|
49
|
+
"default": {
|
|
50
|
+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
SESSION_ENGINE="django.contrib.sessions.backends.signed_cookies",
|
|
54
|
+
AUTHENTICATION_BACKENDS=["django_app.auth_backend.InMemoryBackend"],
|
|
55
|
+
DATABASES={},
|
|
56
|
+
TIME_ZONE="UTC",
|
|
57
|
+
USE_TZ=True,
|
|
58
|
+
DEFAULT_AUTO_FIELD="django.db.models.BigAutoField",
|
|
59
|
+
CORS_ALLOWED_ORIGINS=[
|
|
60
|
+
"http://localhost:3000",
|
|
61
|
+
"https://example.com",
|
|
62
|
+
],
|
|
63
|
+
CORS_ALLOW_CREDENTIALS=True,
|
|
64
|
+
CORS_ALLOWED_ORIGIN_REGEXES=[r"^https://.*\.example\.com$"],
|
|
65
|
+
REST_FRAMEWORK={
|
|
66
|
+
"DEFAULT_RENDERER_CLASSES": ["rest_framework.renderers.JSONRenderer"],
|
|
67
|
+
"DEFAULT_PARSER_CLASSES": [
|
|
68
|
+
"rest_framework.parsers.JSONParser",
|
|
69
|
+
"rest_framework.parsers.FormParser",
|
|
70
|
+
"rest_framework.parsers.MultiPartParser",
|
|
71
|
+
],
|
|
72
|
+
"DEFAULT_THROTTLE_RATES": {
|
|
73
|
+
"anon": "10/min",
|
|
74
|
+
"user": "100/min",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
import django # noqa: E402
|
|
80
|
+
|
|
81
|
+
django.setup()
|
|
82
|
+
|
|
83
|
+
from django.core.handlers.asgi import ASGIHandler # noqa: E402
|
|
84
|
+
|
|
85
|
+
django_asgi_app = ASGIHandler()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class DjangoAppPlugin:
|
|
89
|
+
@pytest.fixture
|
|
90
|
+
def django_asgi_app(self):
|
|
91
|
+
return django_asgi_app
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Default(TestRunnerEntrypoint):
|
|
95
|
+
app = django_asgi_app
|
|
96
|
+
|
|
97
|
+
async def fetch(self, request):
|
|
98
|
+
result = await super().fetch(request)
|
|
99
|
+
if result.status == 404:
|
|
100
|
+
result = await asgi.fetch(django_asgi_app, request, self.env, self.ctx)
|
|
101
|
+
return result
|
|
102
|
+
|
|
103
|
+
def plugins(self):
|
|
104
|
+
return super().plugins() + [DjangoAppPlugin()]
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import enum
|
|
3
3
|
import hashlib
|
|
4
|
-
import importlib.util
|
|
5
4
|
import json
|
|
6
5
|
from contextlib import asynccontextmanager
|
|
7
6
|
from pathlib import Path
|
|
@@ -34,6 +33,7 @@ from pydantic import BaseModel
|
|
|
34
33
|
from pyodide.webloop import WebLoop
|
|
35
34
|
from starlette.background import BackgroundTask
|
|
36
35
|
from starlette.middleware.gzip import GZipMiddleware
|
|
36
|
+
from testlib.entrypoint import TestRunner
|
|
37
37
|
|
|
38
38
|
import asgi
|
|
39
39
|
|
|
@@ -585,57 +585,6 @@ async def native_file():
|
|
|
585
585
|
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
|
|
586
586
|
|
|
587
587
|
|
|
588
|
-
class ResultCollector:
|
|
589
|
-
def __init__(self):
|
|
590
|
-
self.results = {}
|
|
591
|
-
|
|
592
|
-
@staticmethod
|
|
593
|
-
def _key(item):
|
|
594
|
-
name = item.name
|
|
595
|
-
return name[len("test_") :] if name.startswith("test_") else name
|
|
596
|
-
|
|
597
|
-
@pytest.hookimpl(hookwrapper=True)
|
|
598
|
-
def pytest_runtest_makereport(self, item, call):
|
|
599
|
-
outcome = yield
|
|
600
|
-
report = outcome.get_result()
|
|
601
|
-
key = self._key(item)
|
|
602
|
-
|
|
603
|
-
if report.when == "call":
|
|
604
|
-
if report.passed:
|
|
605
|
-
self.results[key] = {"status": "passed"}
|
|
606
|
-
elif report.skipped:
|
|
607
|
-
self.results[key] = {
|
|
608
|
-
"status": "skipped",
|
|
609
|
-
"reason": str(report.longrepr),
|
|
610
|
-
}
|
|
611
|
-
elif report.failed:
|
|
612
|
-
excinfo = call.excinfo
|
|
613
|
-
if excinfo is not None and excinfo.errisinstance(AssertionError):
|
|
614
|
-
self.results[key] = {
|
|
615
|
-
"status": "failed",
|
|
616
|
-
"error": str(excinfo.value),
|
|
617
|
-
}
|
|
618
|
-
else:
|
|
619
|
-
self.results[key] = {
|
|
620
|
-
"status": "error",
|
|
621
|
-
"error": f"{excinfo.typename}: {excinfo.value}"
|
|
622
|
-
if excinfo is not None
|
|
623
|
-
else "unknown error",
|
|
624
|
-
"traceback": report.longreprtext,
|
|
625
|
-
}
|
|
626
|
-
elif report.when in ("setup", "teardown") and report.skipped:
|
|
627
|
-
self.results[key] = {
|
|
628
|
-
"status": "skipped",
|
|
629
|
-
"reason": str(report.longrepr),
|
|
630
|
-
}
|
|
631
|
-
elif report.when in ("setup", "teardown") and report.failed:
|
|
632
|
-
self.results[key] = {
|
|
633
|
-
"status": "error",
|
|
634
|
-
"error": report.longreprtext,
|
|
635
|
-
"traceback": report.longreprtext,
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
|
|
639
588
|
class EnvPlugin:
|
|
640
589
|
def __init__(self, env):
|
|
641
590
|
self._env = env
|
|
@@ -653,27 +602,9 @@ class FastAPIAppPlugin:
|
|
|
653
602
|
|
|
654
603
|
@app.get("/run-tests/{suite_name:path}")
|
|
655
604
|
async def run_suite(suite_name: str, request: Request):
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
{"error": f"Unknown suite '{suite_name}' (no module '{module}')"},
|
|
660
|
-
status_code=404,
|
|
661
|
-
)
|
|
662
|
-
|
|
663
|
-
collector = ResultCollector()
|
|
664
|
-
saved_loop = asyncio.events._get_running_loop()
|
|
665
|
-
try:
|
|
666
|
-
pytest.main(
|
|
667
|
-
["--pyargs", module, "-p", "no:cacheprovider"],
|
|
668
|
-
plugins=[
|
|
669
|
-
collector,
|
|
670
|
-
EnvPlugin(request.scope["env"]),
|
|
671
|
-
FastAPIAppPlugin(),
|
|
672
|
-
],
|
|
673
|
-
)
|
|
674
|
-
finally:
|
|
675
|
-
asyncio.events._set_running_loop(saved_loop)
|
|
676
|
-
return collector.results
|
|
605
|
+
runner = TestRunner(request.scope["env"])
|
|
606
|
+
result = runner.run_suite(suite_name)
|
|
607
|
+
return JSONResponse(result.payload, status_code=result.status)
|
|
677
608
|
|
|
678
609
|
|
|
679
610
|
@app.get("/{path:path}")
|
{workers_runtime_sdk-1.8.2 → workers_runtime_sdk-1.8.4}/tests/workerd-test/asgi/tests/test_asgi.py
RENAMED
|
@@ -428,3 +428,49 @@ async def test_multiple_set_cookie_headers_survive():
|
|
|
428
428
|
"first=1; Path=/",
|
|
429
429
|
"second=2; Path=/",
|
|
430
430
|
]
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class _StartupFailEmptyMessageApp:
|
|
434
|
+
async def __call__(self, scope, receive, send):
|
|
435
|
+
if scope["type"] == "lifespan":
|
|
436
|
+
message = await receive()
|
|
437
|
+
if message["type"] == "lifespan.startup":
|
|
438
|
+
await send({"type": "lifespan.startup.failed", "message": ""})
|
|
439
|
+
return
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
@pytest.mark.asyncio
|
|
443
|
+
async def test_lifespan_startup_failure_with_empty_message():
|
|
444
|
+
req = js.Request.new("http://example.com/startup-fail-empty")
|
|
445
|
+
with pytest.raises(RuntimeError, match="ASGI lifespan startup failed"):
|
|
446
|
+
await asyncio.wait_for(
|
|
447
|
+
asgi.fetch(_StartupFailEmptyMessageApp(), req, env), timeout=5
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
class _PreAckCrashApp:
|
|
452
|
+
"""Raises on the lifespan scope before any ack; HTTP must still serve."""
|
|
453
|
+
|
|
454
|
+
async def __call__(self, scope, receive, send):
|
|
455
|
+
if scope["type"] == "lifespan":
|
|
456
|
+
raise RuntimeError("crashed before ack")
|
|
457
|
+
await receive()
|
|
458
|
+
await send({"type": "http.response.start", "status": 200, "headers": []})
|
|
459
|
+
await send({"type": "http.response.body", "body": b"ok"})
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
@pytest.mark.asyncio
|
|
463
|
+
async def test_lifespan_preack_crash_is_logged_and_treated_as_unsupported():
|
|
464
|
+
handler = _install_handler()
|
|
465
|
+
try:
|
|
466
|
+
req = js.Request.new("http://example.com/preack-crash")
|
|
467
|
+
response = await asyncio.wait_for(
|
|
468
|
+
asgi.fetch(_PreAckCrashApp(), req, env), timeout=5
|
|
469
|
+
)
|
|
470
|
+
assert await response.text() == "ok"
|
|
471
|
+
assert any(
|
|
472
|
+
"before reporting startup" in record.getMessage()
|
|
473
|
+
for record in handler.records
|
|
474
|
+
)
|
|
475
|
+
finally:
|
|
476
|
+
_remove_handler(handler)
|