workers-runtime-sdk 1.8.4__tar.gz → 1.8.6__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.6}/CHANGELOG.md +29 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/pyproject.toml +1 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_workers_sdk_entropy_import_context.py +48 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/entrypoints.py +19 -12
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/utils.py +16 -3
- workers_runtime_sdk-1.8.6/tests/bindings-test/pyproject.toml +19 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_hyperdrive_mysql.py +21 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_hyperdrive_postgresql.py +65 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_workflow.py +26 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/worker_workflow.py +44 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/test_in_workerd.py +28 -10
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/worker.py +1 -1
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +1 -3
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/pyproject.toml +2 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/entropy-patches/tests/test_mcp.py +10 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/entropy-patches/tests/test_opentelemetry.py +8 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/worker.py +2 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/http-client.wd-test +45 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/origin.py +60 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/pyproject.toml +5 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/tests/test_http_client.py +162 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/tests/test_urllib_request.py +121 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/worker.py +14 -0
- workers_runtime_sdk-1.8.6/tests/workerd-test/http-client/wrangler.jsonc +5 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/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.6}/.gitignore +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/AGENTS.md +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/README.md +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_workers_sdk_package_patches.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_workers_sdk_patch_loader.pth +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/_workers_sdk_patch_loader.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/request.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/response.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/src/workers/wsgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/public/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/public/hello.txt +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_analytics_engine.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_d1.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_do.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_images.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_kv.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_mtls.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_queue.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_r2.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_ratelimit.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_vectorize.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_version_metadata.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/worker_durable_object.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/test_bindings.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/test_fastapi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/test_flask.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/test_web_frameworks.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/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.6}/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.6}/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.6}/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.6}/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.6}/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.6}/tests/web-frameworks-test/django-async/src/django_app/forms.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/django_app/middleware.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/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.6}/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.6}/tests/web-frameworks-test/django-async/src/django_app/urls.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/django_app/views.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/templates/base.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/templates/context_test.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/templates/hello.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_async_utilities.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_auth.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_caching.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_cors.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_csrf.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/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.6}/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.6}/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_drf_views.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_file_uploads.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_forms.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_middleware.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_pagination.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_request_response.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_sessions.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_signals.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_streaming.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_templates.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_url_routing.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/test_views_basic.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/django-async/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/public/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/public/index.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/public/style.css +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/_client.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/conftest.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/static/app.css +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/static/data.json +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/static/hello.txt +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/static/index.html +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_error_handling.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_platform_boundaries.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_platform_io.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_platform_lifecycle.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_response_types.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_routing.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_staticfiles.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_sync_handlers.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/src/test_websocket.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/flask-tests/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/flask-tests/src/test_response.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/flask-tests/src/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/web-frameworks-test/flask-tests/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi/asgi.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi/tests/test_asgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi-ws-disconnect/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object/durable-object.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-abort/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-abort/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-abort/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-inheritance/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-inheritance/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-websocket/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-websocket/tester.js +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-websocket/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/durable-object-websocket/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/entropy-patches.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_langsmith.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_litestar.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_numpy.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_pydantic.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/entropy-patches/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/python-rpc/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/python-rpc/python-rpc.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/python-rpc/worker.js +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/python-rpc/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/python-rpc/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/sdk.wd-test +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/server.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/tests/test_sdk.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/sdk/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/wsgi/pyproject.toml +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/wsgi/tests/test_wsgi.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/wsgi/worker.py +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/wsgi/wrangler.jsonc +0 -0
- {workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/workerd-test/wsgi/wsgi.wd-test +0 -0
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.8.6 (2026-09-18)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **runtime-sdk**: Convert workflow step results with python_to_rpc
|
|
10
|
+
([`4220da8`](https://github.com/cloudflare/workers-py/commit/4220da80451073afd7140e091811a8dd4b879aa5))
|
|
11
|
+
|
|
12
|
+
- **runtime-sdk**: Don't crash in _from_js_error on messages without a traceback
|
|
13
|
+
([`a9159df`](https://github.com/cloudflare/workers-py/commit/a9159df2ede8f1a2ff420b8bac1d0e0199506e86))
|
|
14
|
+
|
|
15
|
+
- **runtime-sdk**: Key workflow step memoisation by closure instead of step name
|
|
16
|
+
([`610d18f`](https://github.com/cloudflare/workers-py/commit/610d18f7ce350bbd40cd20312bb26334f67923f5))
|
|
17
|
+
|
|
18
|
+
- **runtime-sdk**: Raise a TypeError for invalid legacy `depends` entries
|
|
19
|
+
([`10a2bcc`](https://github.com/cloudflare/workers-py/commit/10a2bccbe91d06e8c0fb187a661bb78a4d236342))
|
|
20
|
+
|
|
21
|
+
- **runtime-sdk**: Recover Python exception types under enhanced error serialization
|
|
22
|
+
([`53be6db`](https://github.com/cloudflare/workers-py/commit/53be6db4a8ff62e03b2eb4e4896d45d6dd5d748b))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## v1.8.5 (2026-09-17)
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
- **runtime-sdk**: Fix top-level import for opentelemetry package
|
|
30
|
+
([#248](https://github.com/cloudflare/workers-py/pull/248),
|
|
31
|
+
[`338c12e`](https://github.com/cloudflare/workers-py/commit/338c12e5dc6aada9dd20968fdae6bb6e805ad33e))
|
|
32
|
+
|
|
33
|
+
|
|
5
34
|
## v1.8.4 (2026-09-08)
|
|
6
35
|
|
|
7
36
|
### 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.6
|
|
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.6}/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
|
|
@@ -116,7 +116,7 @@ class _WorkflowStepWrapper:
|
|
|
116
116
|
func, depends, implicit
|
|
117
117
|
)
|
|
118
118
|
results = await self._gather_results(results_future_list, concurrent)
|
|
119
|
-
return await _do_call(self, step_name, config, func, *results)
|
|
119
|
+
return await _do_call(self, step_name, wrapper, config, func, *results)
|
|
120
120
|
|
|
121
121
|
wrapper._step_name = step_name
|
|
122
122
|
self.step_closures[step_name] = wrapper
|
|
@@ -157,7 +157,13 @@ class _WorkflowStepWrapper:
|
|
|
157
157
|
if p.name == "ctx":
|
|
158
158
|
results_future_list.append(p)
|
|
159
159
|
else:
|
|
160
|
-
|
|
160
|
+
dep = depends[curr]
|
|
161
|
+
if not hasattr(dep, "_step_name"):
|
|
162
|
+
raise TypeError(
|
|
163
|
+
f"'depends' entry for parameter {p.name!r} is not a "
|
|
164
|
+
"function decorated with step.do"
|
|
165
|
+
)
|
|
166
|
+
results_future_list.append(dep)
|
|
161
167
|
curr += 1
|
|
162
168
|
|
|
163
169
|
return results_future_list
|
|
@@ -194,17 +200,17 @@ class _WorkflowStepWrapper:
|
|
|
194
200
|
)
|
|
195
201
|
|
|
196
202
|
async def _resolve_dependency(self, dep):
|
|
197
|
-
if
|
|
203
|
+
if isinstance(dep, inspect.Parameter) and dep.name == "ctx":
|
|
198
204
|
return dep
|
|
199
|
-
elif dep
|
|
200
|
-
return self._memoized_dependencies[dep
|
|
201
|
-
elif dep
|
|
202
|
-
return await self._in_flight[dep
|
|
205
|
+
elif dep in self._memoized_dependencies:
|
|
206
|
+
return self._memoized_dependencies[dep]
|
|
207
|
+
elif dep in self._in_flight:
|
|
208
|
+
return await self._in_flight[dep]
|
|
203
209
|
|
|
204
210
|
return await dep()
|
|
205
211
|
|
|
206
212
|
|
|
207
|
-
async def _do_call(entrypoint, name, config, callback, *results):
|
|
213
|
+
async def _do_call(entrypoint, name, key, config, callback, *results):
|
|
208
214
|
async def _callback(ctx=None):
|
|
209
215
|
# deconstruct the actual ctx object
|
|
210
216
|
resolved_results = tuple(
|
|
@@ -217,7 +223,8 @@ async def _do_call(entrypoint, name, config, callback, *results):
|
|
|
217
223
|
|
|
218
224
|
if inspect.iscoroutine(result):
|
|
219
225
|
result = await result
|
|
220
|
-
|
|
226
|
+
# The step result crosses the RPC boundary back to the Workflows engine
|
|
227
|
+
return python_to_rpc(result)
|
|
221
228
|
|
|
222
229
|
async def _closure():
|
|
223
230
|
try:
|
|
@@ -233,13 +240,13 @@ async def _do_call(entrypoint, name, config, callback, *results):
|
|
|
233
240
|
raise _from_js_error(exc) from exc
|
|
234
241
|
|
|
235
242
|
task = create_task(_closure())
|
|
236
|
-
entrypoint._in_flight[
|
|
243
|
+
entrypoint._in_flight[key] = task
|
|
237
244
|
|
|
238
245
|
try:
|
|
239
246
|
result = await task
|
|
240
|
-
entrypoint._memoized_dependencies[
|
|
247
|
+
entrypoint._memoized_dependencies[key] = result
|
|
241
248
|
finally:
|
|
242
|
-
|
|
249
|
+
entrypoint._in_flight.pop(key, None)
|
|
243
250
|
|
|
244
251
|
return result
|
|
245
252
|
|
|
@@ -147,11 +147,24 @@ def _to_python_exception(exc: JsException) -> Exception:
|
|
|
147
147
|
def _from_js_error(exc: JsException) -> Exception:
|
|
148
148
|
# convert into Python exception after a full round trip
|
|
149
149
|
# Python - JS - Python
|
|
150
|
-
|
|
150
|
+
message = exc.message or ""
|
|
151
|
+
|
|
152
|
+
# A Python exception that escaped to JS is a Pyodide `PythonError` whose
|
|
153
|
+
# message is the formatted traceback. Depending on how it was serialized
|
|
154
|
+
# over RPC it either keeps its name or arrives as a plain `Error` with
|
|
155
|
+
# "PythonError: " folded into the message.
|
|
156
|
+
if getattr(exc, "name", None) != "PythonError" and not message.startswith(
|
|
157
|
+
"PythonError"
|
|
158
|
+
):
|
|
151
159
|
return _to_python_exception(exc)
|
|
152
160
|
|
|
153
|
-
# extract the Python exception type from the traceback
|
|
154
|
-
|
|
161
|
+
# extract the Python exception type from the last line of the traceback. The
|
|
162
|
+
# message may have been stripped down to just "PythonError" when crossing an RPC
|
|
163
|
+
# boundary, in which case there is no traceback to inspect.
|
|
164
|
+
lines = message.rstrip().split("\n")
|
|
165
|
+
if len(lines) < 2:
|
|
166
|
+
return _to_python_exception(exc)
|
|
167
|
+
error_message_last_line = lines[-1]
|
|
155
168
|
if error_message_last_line.startswith("TypeError"):
|
|
156
169
|
return TypeError(error_message_last_line)
|
|
157
170
|
elif error_message_last_line.startswith("ValueError"):
|
|
@@ -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)
|
{workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/test_workflow.py
RENAMED
|
@@ -159,11 +159,36 @@ async def test_error_handling_catch(env):
|
|
|
159
159
|
# Per the docs, a step error propagates to run() and is catchable with
|
|
160
160
|
# `except Exception`. Neither the concrete type nor the original message is
|
|
161
161
|
# guaranteed to survive the RPC layer, so we assert the reliable contract:
|
|
162
|
-
# the error was caught and a message was produced
|
|
162
|
+
# the error was caught and a message was produced, and that the SDK's own
|
|
163
|
+
# error translation did not blow up (e.g. IndexError while parsing it).
|
|
163
164
|
assert status["output"]["caught"] is not None
|
|
165
|
+
assert status["output"]["caught"] != "IndexError"
|
|
164
166
|
assert status["output"]["message"]
|
|
165
167
|
|
|
166
168
|
|
|
169
|
+
async def test_duplicate_step_names(env):
|
|
170
|
+
instance = await env.MY_WORKFLOW.create(
|
|
171
|
+
{"params": {"mode": "duplicate_step_names"}}
|
|
172
|
+
)
|
|
173
|
+
status = await _poll(instance)
|
|
174
|
+
assert status["status"] == "complete", f"unexpected status: {dict(status)!r}"
|
|
175
|
+
assert status["output"]["concurrent"] == [1, 2]
|
|
176
|
+
assert status["output"]["uses"] == 20
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def test_step_output_conversion(env):
|
|
180
|
+
instance = await env.MY_WORKFLOW.create(
|
|
181
|
+
{"params": {"mode": "step_output_conversion"}}
|
|
182
|
+
)
|
|
183
|
+
status = await _poll(instance)
|
|
184
|
+
assert status["status"] == "complete", f"unexpected status: {dict(status)!r}"
|
|
185
|
+
out = status["output"]
|
|
186
|
+
assert out["when_is_datetime"] is True
|
|
187
|
+
assert out["year"] == 2026
|
|
188
|
+
assert out["nothing_is_none"] is True
|
|
189
|
+
assert out["nested_nothing_is_none"] is True
|
|
190
|
+
|
|
191
|
+
|
|
167
192
|
# The tests below pass pre-converted (to_js) objects, the legacy pattern from the
|
|
168
193
|
# Workflows docs, to ensure existing code keeps working now that the binding
|
|
169
194
|
# auto-converts plain Python objects.
|
{workers_runtime_sdk-1.8.4 → workers_runtime_sdk-1.8.6}/tests/bindings-test/src/worker_workflow.py
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import datetime
|
|
2
3
|
|
|
3
4
|
from workers import WorkflowEntrypoint
|
|
@@ -19,6 +20,8 @@ class TestWorkflow(WorkflowEntrypoint):
|
|
|
19
20
|
"retry": self._retry,
|
|
20
21
|
"non_retryable": self._non_retryable,
|
|
21
22
|
"catch_error": self._catch_error,
|
|
23
|
+
"duplicate_step_names": self._duplicate_step_names,
|
|
24
|
+
"step_output_conversion": self._step_output_conversion,
|
|
22
25
|
}
|
|
23
26
|
handler = handlers.get(mode)
|
|
24
27
|
if handler is None:
|
|
@@ -115,6 +118,47 @@ class TestWorkflow(WorkflowEntrypoint):
|
|
|
115
118
|
|
|
116
119
|
return await boom()
|
|
117
120
|
|
|
121
|
+
async def _duplicate_step_names(self, event, step):
|
|
122
|
+
# The engine disambiguates repeated step names with a counter, so two
|
|
123
|
+
# steps sharing a name must not share memoised results or in-flight tasks.
|
|
124
|
+
@step.do("dup")
|
|
125
|
+
async def first():
|
|
126
|
+
return 1
|
|
127
|
+
|
|
128
|
+
@step.do("dup")
|
|
129
|
+
async def second():
|
|
130
|
+
return 2
|
|
131
|
+
|
|
132
|
+
# Implicit dependencies resolve by step name, so `dup` refers to the most
|
|
133
|
+
# recently registered closure (`second`) and must return its result.
|
|
134
|
+
@step.do()
|
|
135
|
+
async def uses(dup):
|
|
136
|
+
return dup * 10
|
|
137
|
+
|
|
138
|
+
# Run both same-named steps concurrently so they are in flight together.
|
|
139
|
+
concurrent = list(await asyncio.gather(first(), second()))
|
|
140
|
+
return {"concurrent": concurrent, "uses": await uses()}
|
|
141
|
+
|
|
142
|
+
async def _step_output_conversion(self, event, step):
|
|
143
|
+
@step.do("produce")
|
|
144
|
+
async def produce():
|
|
145
|
+
return {
|
|
146
|
+
"when": datetime.datetime(2026, 1, 2, 3, 4, 5),
|
|
147
|
+
"nothing": None,
|
|
148
|
+
"nested": {"nothing": None},
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@step.do()
|
|
152
|
+
async def consume(produce):
|
|
153
|
+
return {
|
|
154
|
+
"when_is_datetime": isinstance(produce["when"], datetime.datetime),
|
|
155
|
+
"year": produce["when"].year,
|
|
156
|
+
"nothing_is_none": produce["nothing"] is None,
|
|
157
|
+
"nested_nothing_is_none": produce["nested"]["nothing"] is None,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return await consume()
|
|
161
|
+
|
|
118
162
|
async def _catch_error(self, event, step):
|
|
119
163
|
@step.do(
|
|
120
164
|
"failing-step",
|
|
@@ -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
|
+
);
|