workers-runtime-sdk 1.6.6__tar.gz → 1.6.7__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.6 → workers_runtime_sdk-1.6.7}/AGENTS.md +1 -1
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/CHANGELOG.md +9 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/PKG-INFO +1 -1
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/pyproject.toml +9 -1
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_workers_sdk_entropy_import_context.py +4 -8
- workers_runtime_sdk-1.6.7/tests/bindings-test/public/data.json +1 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/public/hello.txt +1 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/conftest.py +10 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_analytics_engine.py +24 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_assets.py +35 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_d1.py +498 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_do.py +224 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_images.py +41 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_kv.py +320 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_mtls.py +15 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_queue.py +125 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_r2.py +393 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_ratelimit.py +14 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_vectorize.py +11 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_version_metadata.py +17 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/test_workflow.py +215 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/worker.py +186 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/worker_durable_object.py +260 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/src/worker_workflow.py +130 -0
- workers_runtime_sdk-1.6.7/tests/bindings-test/wrangler.jsonc +65 -0
- workers_runtime_sdk-1.6.7/tests/conftest.py +267 -0
- workers_runtime_sdk-1.6.7/tests/test_bindings.py +27 -0
- workers_runtime_sdk-1.6.7/tests/test_fastapi.py +44 -0
- workers_runtime_sdk-1.6.7/tests/test_in_workerd.py +151 -0
- workers_runtime_sdk-1.6.7/tests/test_web_frameworks.py +41 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/pyproject.toml +11 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/_client.py +92 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/conftest.py +10 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/__init__.py +0 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/api_urls.py +13 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/auth_backend.py +77 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/drf_auth.py +24 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/drf_serializers.py +36 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/drf_throttling.py +12 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/drf_views.py +134 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/forms.py +39 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/middleware.py +17 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/templatetags/__init__.py +0 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/templatetags/custom_tags.py +13 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/urls.py +67 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/django_app/views.py +363 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/templates/base.html +5 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/templates/context_test.html +6 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/templates/csrf_form.html +1 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/templates/hello.html +3 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_async_utilities.py +19 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_auth.py +86 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_caching.py +62 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_cors.py +46 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_csrf.py +69 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_auth_permissions.py +47 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_content_negotiation.py +41 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_serializers.py +68 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_throttling.py +16 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_versioning.py +25 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_drf_views.py +73 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_error_handling.py +32 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_file_uploads.py +57 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_forms.py +50 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_middleware.py +27 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_pagination.py +36 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_request_response.py +98 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_sessions.py +95 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_signals.py +33 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_streaming.py +22 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_templates.py +34 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_url_routing.py +69 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/test_views_basic.py +71 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/src/worker.py +206 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/django-async/wrangler.jsonc +6 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/public/data.json +1 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/public/index.html +7 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/public/style.css +5 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/pyproject.toml +9 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/src/_client.py +26 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/src/conftest.py +10 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/src/test_assets.py +65 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/src/worker.py +143 -0
- workers_runtime_sdk-1.6.7/tests/web-frameworks-test/fastapi-tests/wrangler.jsonc +11 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi/asgi.wd-test +19 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi/tests/test_asgi.py +401 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi/worker.py +240 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi-ws-disconnect/asgi-ws-disconnect.wd-test +19 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi-ws-disconnect/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi-ws-disconnect/tests/test_ws_disconnect.py +72 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi-ws-disconnect/worker.py +70 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/asgi-ws-disconnect/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object/durable-object.wd-test +28 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object/worker.py +144 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-abort/durable-object-abort.wd-test +27 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-abort/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-abort/worker.py +57 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-abort/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-inheritance/durable-object-inheritance.wd-test +40 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-inheritance/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-inheritance/worker.py +115 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-inheritance/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-websocket/durable-object-websocket.wd-test +39 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-websocket/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-websocket/tester.js +27 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-websocket/worker.py +43 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/durable-object-websocket/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/entropy-patches.wd-test +18 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/pyproject.toml +18 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_aiohttp_websocket.py +7 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_langsmith.py +8 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_numpy.py +9 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_pydantic.py +8 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_rust_packages.py +10 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/tests/test_ssl_avoidance.py +9 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/worker.py +27 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/entropy-patches/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/python-rpc/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/python-rpc/python-rpc.wd-test +34 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/python-rpc/worker.js +101 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/python-rpc/worker.py +384 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/python-rpc/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/sdk.wd-test +42 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/server.py +35 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/tests/test_sdk.py +608 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/worker.py +71 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/sdk/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/wsgi/pyproject.toml +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/wsgi/worker.py +205 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/wsgi/wrangler.jsonc +5 -0
- workers_runtime_sdk-1.6.7/tests/workerd-test/wsgi/wsgi.wd-test +19 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/uv.lock +119 -1
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/.gitignore +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/README.md +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_cloudflare_compat_flags.pyi +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_pyodide_entrypoint_helper.pyi +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_workers_sdk_entropy_import_context.pth +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_workers_sdk_entropy_import_context_loader.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/asgi.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/__init__.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/blob.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/entrypoints.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/fetch.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/formdata.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/py.typed +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/request.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/response.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/rpc.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/types.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/utils.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/workflows.py +0 -0
- {workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/workers/wsgi.py +0 -0
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v1.6.7 (2026-08-05)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Fix entropy patch for newer pydantic versions
|
|
10
|
+
([#153](https://github.com/cloudflare/workers-py/pull/153),
|
|
11
|
+
[`81a4b6b`](https://github.com/cloudflare/workers-py/commit/81a4b6bad37373e0b448dd2dbedbf6cec0f47b8c))
|
|
12
|
+
|
|
13
|
+
|
|
5
14
|
## v1.6.6 (2026-08-03)
|
|
6
15
|
|
|
7
16
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workers-runtime-sdk
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.7
|
|
4
4
|
Summary: Python SDK for Cloudflare Workers
|
|
5
5
|
Project-URL: Homepage, https://github.com/cloudflare/workers-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/cloudflare/workers-py/issues
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "workers-runtime-sdk"
|
|
7
|
-
version = "1.6.
|
|
7
|
+
version = "1.6.7"
|
|
8
8
|
description = "Python SDK for Cloudflare Workers"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -20,6 +20,7 @@ dev = [
|
|
|
20
20
|
"pytest>=7.0.0",
|
|
21
21
|
"ruff>=0.1.0",
|
|
22
22
|
"mypy>=1.0.0",
|
|
23
|
+
"requests>=2.28.0",
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
[project.urls]
|
|
@@ -56,6 +57,13 @@ lint.ignore = [
|
|
|
56
57
|
"UP038", # Use X | Y instead of (X, Y)
|
|
57
58
|
]
|
|
58
59
|
lint.flake8-comprehensions.allow-dict-calls-with-keyword-arguments = true
|
|
60
|
+
lint.per-file-ignores."tests/**" = ["PLR2004", "PLR0913"]
|
|
61
|
+
lint.per-file-ignores."tests/workerd-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
|
|
62
|
+
lint.per-file-ignores."tests/bindings-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
|
|
63
|
+
lint.per-file-ignores."tests/web-frameworks-test/**" = ["C901", "PLR0911", "PLR0912", "PLR2004", "PLW0603"]
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
addopts = ["--ignore=tests/workerd-test", "--ignore=tests/bindings-test", "--ignore=tests/web-frameworks-test"]
|
|
59
67
|
|
|
60
68
|
[tool.mypy]
|
|
61
69
|
packages = ["workers_runtime_sdk"]
|
{workers_runtime_sdk-1.6.6 → workers_runtime_sdk-1.6.7}/src/_workers_sdk_entropy_import_context.py
RENAMED
|
@@ -93,14 +93,10 @@ def pydantic_core_context(module):
|
|
|
93
93
|
with allow_bad_entropy_calls(1):
|
|
94
94
|
yield
|
|
95
95
|
finally:
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# but only after making the needed entropy call.
|
|
101
|
-
module.validate_core_schema(None)
|
|
102
|
-
except module.SchemaError:
|
|
103
|
-
pass
|
|
96
|
+
# Build a tiny validator instead so any lazy hash-map seeds are initialized
|
|
97
|
+
# before the snapshot is captured.
|
|
98
|
+
with allow_bad_entropy_calls(1):
|
|
99
|
+
module.SchemaValidator({"type": "any"})
|
|
104
100
|
|
|
105
101
|
|
|
106
102
|
@register_exec_patch("aiohttp.http_websocket")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"key": "value", "number": 42}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hello from static assets
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from workers.rpc import _BindingWrapper
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.asyncio
|
|
7
|
+
async def test_is_wrapped(env):
|
|
8
|
+
assert isinstance(env.ANALYTICS, _BindingWrapper)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.asyncio
|
|
12
|
+
async def test_write_data_point_blobs_and_doubles(env):
|
|
13
|
+
env.ANALYTICS.writeDataPoint(
|
|
14
|
+
{
|
|
15
|
+
"blobs": ["blob1", "blob2"],
|
|
16
|
+
"doubles": [1.0, 2.5],
|
|
17
|
+
"indexes": ["idx"],
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.mark.asyncio
|
|
23
|
+
async def test_write_data_point_empty(env):
|
|
24
|
+
env.ANALYTICS.writeDataPoint({})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from workers.rpc import _FetcherWrapper
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.asyncio
|
|
7
|
+
async def test_is_fetcher_wrapper(env):
|
|
8
|
+
assert isinstance(env.ASSETS, _FetcherWrapper)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.asyncio
|
|
12
|
+
async def test_fetch_text_file(env):
|
|
13
|
+
resp = await env.ASSETS.fetch("https://assets.local/hello.txt")
|
|
14
|
+
text = await resp.text()
|
|
15
|
+
assert text.strip() == "hello from static assets"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.asyncio
|
|
19
|
+
async def test_fetch_json_file(env):
|
|
20
|
+
resp = await env.ASSETS.fetch("https://assets.local/data.json")
|
|
21
|
+
data = await resp.json()
|
|
22
|
+
assert data["key"] == "value"
|
|
23
|
+
assert data["number"] == 42
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.mark.asyncio
|
|
27
|
+
async def test_fetch_returns_404_for_missing(env):
|
|
28
|
+
resp = await env.ASSETS.fetch("https://assets.local/nonexistent.txt")
|
|
29
|
+
assert resp.status == 404
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.asyncio
|
|
33
|
+
async def test_fetch_content_type(env):
|
|
34
|
+
resp = await env.ASSETS.fetch("https://assets.local/data.json")
|
|
35
|
+
assert "application/json" in resp.headers.get("content-type")
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pyodide.ffi import JsException
|
|
3
|
+
|
|
4
|
+
from workers.rpc import _BindingWrapper, _RpcStubWrapper
|
|
5
|
+
|
|
6
|
+
TEST_TABLE = "_test_d1"
|
|
7
|
+
TEST_TABLE_TYPES = "_test_d1_types"
|
|
8
|
+
TEST_TABLE_BATCH = "_test_d1_batch"
|
|
9
|
+
EXEC_TABLE = "_test_d1_exec_tmp"
|
|
10
|
+
EXEC_MULTI_TABLE = "_test_d1_exec_multi"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def _cleanup_d1(db):
|
|
14
|
+
for table in [
|
|
15
|
+
TEST_TABLE,
|
|
16
|
+
TEST_TABLE_TYPES,
|
|
17
|
+
TEST_TABLE_BATCH,
|
|
18
|
+
EXEC_TABLE,
|
|
19
|
+
EXEC_MULTI_TABLE,
|
|
20
|
+
]:
|
|
21
|
+
try:
|
|
22
|
+
await db.exec(f"DROP TABLE IF EXISTS {table}")
|
|
23
|
+
except Exception:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def _ensure_tables(db):
|
|
28
|
+
await db.exec(
|
|
29
|
+
f"CREATE TABLE IF NOT EXISTS {TEST_TABLE} "
|
|
30
|
+
f"(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, value TEXT)"
|
|
31
|
+
)
|
|
32
|
+
await db.exec(
|
|
33
|
+
f"CREATE TABLE IF NOT EXISTS {TEST_TABLE_TYPES} "
|
|
34
|
+
f"(id INTEGER PRIMARY KEY, txt TEXT, num REAL, intval INTEGER)"
|
|
35
|
+
)
|
|
36
|
+
await db.exec(
|
|
37
|
+
f"CREATE TABLE IF NOT EXISTS {TEST_TABLE_BATCH} "
|
|
38
|
+
f"(id INTEGER PRIMARY KEY, val TEXT)"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.mark.asyncio
|
|
43
|
+
async def test_chained_statements_stay_binding_wrappers(env):
|
|
44
|
+
# A binding method returning another binding object must keep the plain
|
|
45
|
+
# binding wrapper.
|
|
46
|
+
statement = env.DB.prepare(f"SELECT 1 FROM {TEST_TABLE} WHERE name = ?")
|
|
47
|
+
assert isinstance(statement, _BindingWrapper)
|
|
48
|
+
assert not isinstance(statement, _RpcStubWrapper)
|
|
49
|
+
assert not callable(statement)
|
|
50
|
+
|
|
51
|
+
bound = statement.bind("x")
|
|
52
|
+
assert isinstance(bound, _BindingWrapper)
|
|
53
|
+
assert not isinstance(bound, _RpcStubWrapper)
|
|
54
|
+
assert not callable(bound)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@pytest.mark.asyncio
|
|
58
|
+
async def test_insert_and_select_via_run(env):
|
|
59
|
+
db = env.DB
|
|
60
|
+
await _cleanup_d1(db)
|
|
61
|
+
await _ensure_tables(db)
|
|
62
|
+
insert_result = (
|
|
63
|
+
await db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
64
|
+
.bind("run_test", "hello")
|
|
65
|
+
.run()
|
|
66
|
+
)
|
|
67
|
+
assert insert_result["success"] is True
|
|
68
|
+
meta = insert_result["meta"]
|
|
69
|
+
assert meta["changes"] >= 1
|
|
70
|
+
assert meta["last_row_id"] > 0
|
|
71
|
+
row_id = meta["last_row_id"]
|
|
72
|
+
select_result = (
|
|
73
|
+
await db.prepare(f"SELECT id, name, value FROM {TEST_TABLE} WHERE id = ?")
|
|
74
|
+
.bind(row_id)
|
|
75
|
+
.run()
|
|
76
|
+
)
|
|
77
|
+
rows = select_result["results"]
|
|
78
|
+
assert len(rows) == 1
|
|
79
|
+
assert rows[0]["name"] == "run_test"
|
|
80
|
+
assert rows[0]["value"] == "hello"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@pytest.mark.asyncio
|
|
84
|
+
async def test_all_returns_results(env):
|
|
85
|
+
db = env.DB
|
|
86
|
+
await _cleanup_d1(db)
|
|
87
|
+
await _ensure_tables(db)
|
|
88
|
+
await (
|
|
89
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
90
|
+
.bind("all_test", "v1")
|
|
91
|
+
.run()
|
|
92
|
+
)
|
|
93
|
+
result = (
|
|
94
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ?")
|
|
95
|
+
.bind("all_test")
|
|
96
|
+
.all()
|
|
97
|
+
)
|
|
98
|
+
assert result["success"] is True
|
|
99
|
+
rows = result["results"]
|
|
100
|
+
assert len(rows) >= 1
|
|
101
|
+
assert rows[0]["name"] == "all_test"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pytest.mark.asyncio
|
|
105
|
+
async def test_first_returns_single_row(env):
|
|
106
|
+
db = env.DB
|
|
107
|
+
await _cleanup_d1(db)
|
|
108
|
+
await _ensure_tables(db)
|
|
109
|
+
await (
|
|
110
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
111
|
+
.bind("first_test", "fv")
|
|
112
|
+
.run()
|
|
113
|
+
)
|
|
114
|
+
row = (
|
|
115
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
116
|
+
.bind("first_test")
|
|
117
|
+
.first()
|
|
118
|
+
)
|
|
119
|
+
assert row is not None, "first() returned None"
|
|
120
|
+
assert isinstance(row, dict)
|
|
121
|
+
assert row["name"] == "first_test"
|
|
122
|
+
assert row["value"] == "fv"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.mark.asyncio
|
|
126
|
+
async def test_first_with_column_name(env):
|
|
127
|
+
db = env.DB
|
|
128
|
+
await _cleanup_d1(db)
|
|
129
|
+
await _ensure_tables(db)
|
|
130
|
+
await (
|
|
131
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
132
|
+
.bind("first_col", "col_val")
|
|
133
|
+
.run()
|
|
134
|
+
)
|
|
135
|
+
value = (
|
|
136
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
137
|
+
.bind("first_col")
|
|
138
|
+
.first("value")
|
|
139
|
+
)
|
|
140
|
+
assert value == "col_val"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@pytest.mark.asyncio
|
|
144
|
+
async def test_first_on_empty_result(env):
|
|
145
|
+
db = env.DB
|
|
146
|
+
await _cleanup_d1(db)
|
|
147
|
+
await _ensure_tables(db)
|
|
148
|
+
row = (
|
|
149
|
+
await db.prepare(f"SELECT * FROM {TEST_TABLE} WHERE name = ?")
|
|
150
|
+
.bind("__nonexistent__xyz__")
|
|
151
|
+
.first()
|
|
152
|
+
)
|
|
153
|
+
assert row is None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@pytest.mark.asyncio
|
|
157
|
+
async def test_raw_returns_arrays(env):
|
|
158
|
+
db = env.DB
|
|
159
|
+
await _cleanup_d1(db)
|
|
160
|
+
await _ensure_tables(db)
|
|
161
|
+
await (
|
|
162
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
163
|
+
.bind("raw_test", "rv")
|
|
164
|
+
.run()
|
|
165
|
+
)
|
|
166
|
+
rows = (
|
|
167
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
168
|
+
.bind("raw_test")
|
|
169
|
+
.raw()
|
|
170
|
+
)
|
|
171
|
+
assert isinstance(rows, list)
|
|
172
|
+
assert len(rows) == 1
|
|
173
|
+
assert rows[0] == ["raw_test", "rv"]
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@pytest.mark.asyncio
|
|
177
|
+
async def test_raw_with_column_names(env):
|
|
178
|
+
db = env.DB
|
|
179
|
+
await _cleanup_d1(db)
|
|
180
|
+
await _ensure_tables(db)
|
|
181
|
+
await (
|
|
182
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
183
|
+
.bind("raw_cols", "rc")
|
|
184
|
+
.run()
|
|
185
|
+
)
|
|
186
|
+
rows = (
|
|
187
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
188
|
+
.bind("raw_cols")
|
|
189
|
+
.raw(columnNames=True)
|
|
190
|
+
)
|
|
191
|
+
assert len(rows) == 2
|
|
192
|
+
assert rows[0] == ["name", "value"]
|
|
193
|
+
assert rows[1] == ["raw_cols", "rc"]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@pytest.mark.asyncio
|
|
197
|
+
async def test_bind_types(env):
|
|
198
|
+
db = env.DB
|
|
199
|
+
await _cleanup_d1(db)
|
|
200
|
+
await _ensure_tables(db)
|
|
201
|
+
|
|
202
|
+
await (
|
|
203
|
+
db.prepare(
|
|
204
|
+
f"INSERT INTO {TEST_TABLE_TYPES} (id, txt, num, intval) VALUES (?, ?, ?, ?)"
|
|
205
|
+
)
|
|
206
|
+
.bind(2, "hello, D1!", 3.14, 42)
|
|
207
|
+
.run()
|
|
208
|
+
)
|
|
209
|
+
await (
|
|
210
|
+
db.prepare(f"INSERT INTO {TEST_TABLE_TYPES} (id, intval) VALUES (?, ?)")
|
|
211
|
+
.bind(3, True)
|
|
212
|
+
.run()
|
|
213
|
+
)
|
|
214
|
+
await (
|
|
215
|
+
db.prepare(f"INSERT INTO {TEST_TABLE_TYPES} (id, intval) VALUES (?, ?)")
|
|
216
|
+
.bind(4, False)
|
|
217
|
+
.run()
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
row2 = (
|
|
221
|
+
await db.prepare(
|
|
222
|
+
f"SELECT txt, num, intval FROM {TEST_TABLE_TYPES} WHERE id = ?"
|
|
223
|
+
)
|
|
224
|
+
.bind(2)
|
|
225
|
+
.first()
|
|
226
|
+
)
|
|
227
|
+
assert row2["txt"] == "hello, D1!"
|
|
228
|
+
assert abs(row2["num"] - 3.14) < 0.001
|
|
229
|
+
assert row2["intval"] == 42
|
|
230
|
+
|
|
231
|
+
row3 = (
|
|
232
|
+
await db.prepare(f"SELECT intval FROM {TEST_TABLE_TYPES} WHERE id = ?")
|
|
233
|
+
.bind(3)
|
|
234
|
+
.first()
|
|
235
|
+
)
|
|
236
|
+
row4 = (
|
|
237
|
+
await db.prepare(f"SELECT intval FROM {TEST_TABLE_TYPES} WHERE id = ?")
|
|
238
|
+
.bind(4)
|
|
239
|
+
.first()
|
|
240
|
+
)
|
|
241
|
+
assert row3["intval"] == 1
|
|
242
|
+
assert row4["intval"] == 0
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@pytest.mark.asyncio
|
|
246
|
+
async def test_exec_create_and_query(env):
|
|
247
|
+
db = env.DB
|
|
248
|
+
await _cleanup_d1(db)
|
|
249
|
+
result = await db.exec(
|
|
250
|
+
f"CREATE TABLE IF NOT EXISTS {EXEC_TABLE} (id INTEGER PRIMARY KEY, val TEXT)"
|
|
251
|
+
)
|
|
252
|
+
assert result["count"] >= 1
|
|
253
|
+
assert result["duration"] >= 0
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@pytest.mark.asyncio
|
|
257
|
+
async def test_exec_multiple_statements(env):
|
|
258
|
+
db = env.DB
|
|
259
|
+
await _cleanup_d1(db)
|
|
260
|
+
result = await db.exec(
|
|
261
|
+
f"CREATE TABLE IF NOT EXISTS {EXEC_MULTI_TABLE} (id INTEGER PRIMARY KEY, val TEXT);\n"
|
|
262
|
+
f"INSERT INTO {EXEC_MULTI_TABLE} (val) VALUES ('a');\n"
|
|
263
|
+
f"INSERT INTO {EXEC_MULTI_TABLE} (val) VALUES ('b');"
|
|
264
|
+
)
|
|
265
|
+
assert result["count"] >= 3
|
|
266
|
+
rows = await db.prepare(f"SELECT val FROM {EXEC_MULTI_TABLE} ORDER BY val").raw()
|
|
267
|
+
assert rows == [["a"], ["b"]]
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@pytest.mark.asyncio
|
|
271
|
+
async def test_batch_multiple_inserts(env):
|
|
272
|
+
db = env.DB
|
|
273
|
+
await _cleanup_d1(db)
|
|
274
|
+
await _ensure_tables(db)
|
|
275
|
+
statements = [
|
|
276
|
+
db.prepare(f"INSERT INTO {TEST_TABLE_BATCH} (id, val) VALUES (?, ?)").bind(
|
|
277
|
+
1, "batch_a"
|
|
278
|
+
),
|
|
279
|
+
db.prepare(f"INSERT INTO {TEST_TABLE_BATCH} (id, val) VALUES (?, ?)").bind(
|
|
280
|
+
2, "batch_b"
|
|
281
|
+
),
|
|
282
|
+
db.prepare(f"INSERT INTO {TEST_TABLE_BATCH} (id, val) VALUES (?, ?)").bind(
|
|
283
|
+
3, "batch_c"
|
|
284
|
+
),
|
|
285
|
+
]
|
|
286
|
+
results = await db.batch(statements)
|
|
287
|
+
assert results is not None, "batch returned None"
|
|
288
|
+
all_rows = await db.prepare(
|
|
289
|
+
f"SELECT id, val FROM {TEST_TABLE_BATCH} ORDER BY id"
|
|
290
|
+
).all()
|
|
291
|
+
rows = all_rows["results"]
|
|
292
|
+
assert len(rows) == 3
|
|
293
|
+
assert [row["val"] for row in rows] == ["batch_a", "batch_b", "batch_c"]
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
@pytest.mark.asyncio
|
|
297
|
+
async def test_run_metadata_fields(env):
|
|
298
|
+
db = env.DB
|
|
299
|
+
await _cleanup_d1(db)
|
|
300
|
+
await _ensure_tables(db)
|
|
301
|
+
result = (
|
|
302
|
+
await db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
303
|
+
.bind("meta_test", "mv")
|
|
304
|
+
.run()
|
|
305
|
+
)
|
|
306
|
+
assert result["success"] is True
|
|
307
|
+
meta = result["meta"]
|
|
308
|
+
for key in [
|
|
309
|
+
"duration",
|
|
310
|
+
"changes",
|
|
311
|
+
"last_row_id",
|
|
312
|
+
"changed_db",
|
|
313
|
+
"rows_read",
|
|
314
|
+
"rows_written",
|
|
315
|
+
"size_after",
|
|
316
|
+
]:
|
|
317
|
+
assert key in meta
|
|
318
|
+
assert meta["changes"] >= 1
|
|
319
|
+
assert meta["changed_db"] is True
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
@pytest.mark.asyncio
|
|
323
|
+
async def test_update_row(env):
|
|
324
|
+
db = env.DB
|
|
325
|
+
await _cleanup_d1(db)
|
|
326
|
+
await _ensure_tables(db)
|
|
327
|
+
insert_result = (
|
|
328
|
+
await db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
329
|
+
.bind("update_me", "old_value")
|
|
330
|
+
.run()
|
|
331
|
+
)
|
|
332
|
+
row_id = insert_result["meta"]["last_row_id"]
|
|
333
|
+
update_result = (
|
|
334
|
+
await db.prepare(f"UPDATE {TEST_TABLE} SET value = ? WHERE id = ?")
|
|
335
|
+
.bind("new_value", row_id)
|
|
336
|
+
.run()
|
|
337
|
+
)
|
|
338
|
+
assert update_result["meta"]["changes"] == 1
|
|
339
|
+
row = (
|
|
340
|
+
await db.prepare(f"SELECT value FROM {TEST_TABLE} WHERE id = ?")
|
|
341
|
+
.bind(row_id)
|
|
342
|
+
.first()
|
|
343
|
+
)
|
|
344
|
+
assert row["value"] == "new_value"
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@pytest.mark.asyncio
|
|
348
|
+
async def test_delete_row(env):
|
|
349
|
+
db = env.DB
|
|
350
|
+
await _cleanup_d1(db)
|
|
351
|
+
await _ensure_tables(db)
|
|
352
|
+
insert_result = (
|
|
353
|
+
await db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
354
|
+
.bind("delete_me", "gone")
|
|
355
|
+
.run()
|
|
356
|
+
)
|
|
357
|
+
row_id = insert_result["meta"]["last_row_id"]
|
|
358
|
+
delete_result = (
|
|
359
|
+
await db.prepare(f"DELETE FROM {TEST_TABLE} WHERE id = ?").bind(row_id).run()
|
|
360
|
+
)
|
|
361
|
+
assert delete_result["meta"]["changes"] == 1
|
|
362
|
+
row = (
|
|
363
|
+
await db.prepare(f"SELECT * FROM {TEST_TABLE} WHERE id = ?")
|
|
364
|
+
.bind(row_id)
|
|
365
|
+
.first()
|
|
366
|
+
)
|
|
367
|
+
assert row is None
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@pytest.mark.asyncio
|
|
371
|
+
async def test_session_prepare_and_query(env):
|
|
372
|
+
db = env.DB
|
|
373
|
+
await _cleanup_d1(db)
|
|
374
|
+
await _ensure_tables(db)
|
|
375
|
+
await (
|
|
376
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
377
|
+
.bind("session_test", "sv")
|
|
378
|
+
.run()
|
|
379
|
+
)
|
|
380
|
+
session = db.withSession()
|
|
381
|
+
assert session is not None, "withSession() returned None"
|
|
382
|
+
result = await session.prepare(f"SELECT COUNT(*) as cnt FROM {TEST_TABLE}").all()
|
|
383
|
+
assert result["success"] is True
|
|
384
|
+
assert result["results"][0]["cnt"] >= 1
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
@pytest.mark.asyncio
|
|
388
|
+
async def test_session_bookmark(env):
|
|
389
|
+
db = env.DB
|
|
390
|
+
await _cleanup_d1(db)
|
|
391
|
+
await _ensure_tables(db)
|
|
392
|
+
session = db.withSession()
|
|
393
|
+
bookmark_before = session.getBookmark()
|
|
394
|
+
assert bookmark_before is None
|
|
395
|
+
await session.prepare("SELECT 1").all()
|
|
396
|
+
bookmark_after = session.getBookmark()
|
|
397
|
+
assert bookmark_after is not None
|
|
398
|
+
assert isinstance(bookmark_after, str)
|
|
399
|
+
assert len(bookmark_after) > 0
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@pytest.mark.asyncio
|
|
403
|
+
async def test_session_batch(env):
|
|
404
|
+
db = env.DB
|
|
405
|
+
await _cleanup_d1(db)
|
|
406
|
+
await _ensure_tables(db)
|
|
407
|
+
session = db.withSession()
|
|
408
|
+
statements = [
|
|
409
|
+
session.prepare(f"INSERT INTO {TEST_TABLE_BATCH} (id, val) VALUES (?, ?)").bind(
|
|
410
|
+
1, "sa"
|
|
411
|
+
),
|
|
412
|
+
session.prepare(f"INSERT INTO {TEST_TABLE_BATCH} (id, val) VALUES (?, ?)").bind(
|
|
413
|
+
2, "sb"
|
|
414
|
+
),
|
|
415
|
+
]
|
|
416
|
+
results = await session.batch(statements)
|
|
417
|
+
assert results is not None, "session batch returned None"
|
|
418
|
+
rows = await session.prepare(
|
|
419
|
+
f"SELECT id, val FROM {TEST_TABLE_BATCH} ORDER BY id"
|
|
420
|
+
).all()
|
|
421
|
+
assert len(rows["results"]) == 2
|
|
422
|
+
assert rows["results"][0]["val"] == "sa"
|
|
423
|
+
assert rows["results"][1]["val"] == "sb"
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@pytest.mark.asyncio
|
|
427
|
+
async def test_invalid_sql_raises_error(env):
|
|
428
|
+
db = env.DB
|
|
429
|
+
await _cleanup_d1(db)
|
|
430
|
+
with pytest.raises(JsException, match="syntax error"):
|
|
431
|
+
await db.prepare("INVALID SQL GIBBERISH").run()
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
@pytest.mark.asyncio
|
|
435
|
+
async def test_raw_dict_column_names(env):
|
|
436
|
+
db = env.DB
|
|
437
|
+
await _cleanup_d1(db)
|
|
438
|
+
await _ensure_tables(db)
|
|
439
|
+
await (
|
|
440
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
441
|
+
.bind("dict_raw", "dr")
|
|
442
|
+
.run()
|
|
443
|
+
)
|
|
444
|
+
rows = await (
|
|
445
|
+
db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
446
|
+
.bind("dict_raw")
|
|
447
|
+
.raw({"columnNames": True})
|
|
448
|
+
)
|
|
449
|
+
assert len(rows) == 2
|
|
450
|
+
assert rows[0] == ["name", "value"]
|
|
451
|
+
assert rows[1] == ["dict_raw", "dr"]
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
@pytest.mark.asyncio
|
|
455
|
+
async def test_bind_null(env):
|
|
456
|
+
import sys
|
|
457
|
+
|
|
458
|
+
if sys.version_info < (3, 13):
|
|
459
|
+
pytest.skip("Pyodide 0.26 (Python 3.12) cannot represent JS null")
|
|
460
|
+
db = env.DB
|
|
461
|
+
await _cleanup_d1(db)
|
|
462
|
+
await _ensure_tables(db)
|
|
463
|
+
await (
|
|
464
|
+
db.prepare(
|
|
465
|
+
f"INSERT INTO {TEST_TABLE_TYPES} (id, txt, num, intval) VALUES (?, ?, ?, ?)"
|
|
466
|
+
)
|
|
467
|
+
.bind(1, None, None, None)
|
|
468
|
+
.run()
|
|
469
|
+
)
|
|
470
|
+
row = (
|
|
471
|
+
await db.prepare(
|
|
472
|
+
f"SELECT txt, num, intval FROM {TEST_TABLE_TYPES} WHERE id = ?"
|
|
473
|
+
)
|
|
474
|
+
.bind(1)
|
|
475
|
+
.first()
|
|
476
|
+
)
|
|
477
|
+
assert row["txt"] is None
|
|
478
|
+
assert row["num"] is None
|
|
479
|
+
assert row["intval"] is None
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
@pytest.mark.asyncio
|
|
483
|
+
async def test_none_options_raw(env):
|
|
484
|
+
db = env.DB
|
|
485
|
+
await _cleanup_d1(db)
|
|
486
|
+
await _ensure_tables(db)
|
|
487
|
+
await (
|
|
488
|
+
db.prepare(f"INSERT INTO {TEST_TABLE} (name, value) VALUES (?, ?)")
|
|
489
|
+
.bind("none_raw", "nr")
|
|
490
|
+
.run()
|
|
491
|
+
)
|
|
492
|
+
rows = (
|
|
493
|
+
await db.prepare(f"SELECT name, value FROM {TEST_TABLE} WHERE name = ? LIMIT 1")
|
|
494
|
+
.bind("none_raw")
|
|
495
|
+
.raw(None)
|
|
496
|
+
)
|
|
497
|
+
assert len(rows) == 1
|
|
498
|
+
assert rows[0] == ["none_raw", "nr"]
|