encore-dev 2.0.0a15__tar.gz → 2.0.0a17__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.
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/PKG-INFO +27 -219
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/README.md +26 -218
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/config/__init__.py +1 -1
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/postgres/__init__.py +41 -17
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/pyproject.toml +1 -1
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/pyproject.toml.orig +1 -1
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/config/_build.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/config/_markers.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/cron/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/env/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/_loader.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/_native.pyi +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/lazy.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/runtime.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/internal/startup.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/logs/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/logs/_console.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/logs/_runtime.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/metrics/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/metrics/_instrument.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/metrics/_metrics.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/metrics/_provider.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/pubsub/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/py.typed +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/secrets/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/services/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/shutdown/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/objects/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/_base.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/_responses.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/_values.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/bitmap.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/generic.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/geo.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/hash.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/json.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/list.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/pubsub.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/set.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/sorted_set.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/stream.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/storage/redis/string.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/__init__.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/_context.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/_encode.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/_provider.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/_span.py +0 -0
- {encore_dev-2.0.0a15 → encore_dev-2.0.0a17}/encore/tracing/_tracer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: encore-dev
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.0a17
|
|
4
4
|
Summary: Encore SDK for Python — infrastructure resources
|
|
5
5
|
Author: Encore
|
|
6
6
|
License: MPL-2.0
|
|
@@ -15,16 +15,29 @@ Description-Content-Type: text/markdown
|
|
|
15
15
|
|
|
16
16
|
The Python SDK for [Encore](https://encore.dev) — **infrastructure resources only**.
|
|
17
17
|
|
|
18
|
-
The distribution is named `encore-dev`; Python code imports it as `encore`.
|
|
19
|
-
|
|
20
18
|
Declare infrastructure (SQL databases, pub/sub topics & subscriptions, object
|
|
21
19
|
storage buckets, Redis databases, cron jobs, metrics, secrets) as module-level variables.
|
|
22
|
-
Encore
|
|
23
|
-
|
|
24
|
-
infrastructure at run time.
|
|
20
|
+
Encore discovers these declarations, provisions the resources, and connects your
|
|
21
|
+
application to them at runtime.
|
|
25
22
|
|
|
26
23
|
Services are declared by the language-agnostic `encore.service.json` file, not in
|
|
27
|
-
Python
|
|
24
|
+
Python. Use the SDK with your preferred Python web framework.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Requires Python 3.9 or later. Install from PyPI with pip:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
python -m pip install encore-dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or add it to a uv project:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
uv add encore-dev
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Declare resources
|
|
28
41
|
|
|
29
42
|
```python
|
|
30
43
|
from encore import pubsub, secrets
|
|
@@ -65,7 +78,8 @@ Declare `postgres.Database("orders", migrations="./migrations")` at module scope
|
|
|
65
78
|
reference a database declared elsewhere.
|
|
66
79
|
|
|
67
80
|
`query(sql, *params)` returns a `Cursor`. Use `async for` to stream rows,
|
|
68
|
-
`await query.one()` to fetch one row
|
|
81
|
+
`await query.one()` to fetch exactly one row (raising `EncoreError` on no rows or
|
|
82
|
+
more than one), `await query.first()` to fetch the first row or `None`, or
|
|
69
83
|
`await query.all()` to collect all rows in a list. Each query can be consumed
|
|
70
84
|
once. Reusing it or mixing helpers with iteration raises `EncoreError`, including
|
|
71
85
|
after partial iteration or an error. Helpers close their cursors automatically.
|
|
@@ -77,7 +91,7 @@ dictionaries keyed by column name. Values are bound with `$1`, `$2`, etc.
|
|
|
77
91
|
|
|
78
92
|
```python
|
|
79
93
|
async def find_order(database: postgres.Queryable, order_id: int):
|
|
80
|
-
return await database.query("SELECT * FROM orders WHERE id = $1", order_id).
|
|
94
|
+
return await database.query("SELECT * FROM orders WHERE id = $1", order_id).first()
|
|
81
95
|
|
|
82
96
|
|
|
83
97
|
async def handle_order(order_id: int):
|
|
@@ -91,7 +105,7 @@ select `read()`, `write()`, or `admin()` before handing it to another function.
|
|
|
91
105
|
Direct database operations infer writer permissions. Reference creation records
|
|
92
106
|
reader, writer, or admin permissions at that call site.
|
|
93
107
|
|
|
94
|
-
|
|
108
|
+
Handles share the database's pool. A `read()` handle runs on
|
|
95
109
|
read-only connections, so its writes fail with SQLSTATE 25006 and its
|
|
96
110
|
transactions are read-only; it reads from the database's read-only pool on a
|
|
97
111
|
replica if the runtime config has one, unless `primary=True` is set.
|
|
@@ -122,11 +136,6 @@ async def first_order():
|
|
|
122
136
|
return row
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
Native Postgres integration tests can be enabled with
|
|
126
|
-
`ENCORE_PYTHON_POSTGRES_TEST_HOST=host:port`. They expect an isolated Postgres
|
|
127
|
-
instance with database/user `postgres` and password `encore-test`, and create and
|
|
128
|
-
remove a temporary schema.
|
|
129
|
-
|
|
130
139
|
## Pub/Sub payloads
|
|
131
140
|
|
|
132
141
|
Use `pubsub.Subscription[T]` to choose how payloads are decoded. Encore validates
|
|
@@ -303,94 +312,9 @@ If cleanup panics after the deadline has already recorded `Timeout`, the core
|
|
|
303
312
|
logs the failure and preserves `Timeout` as the reported result. A timeout is
|
|
304
313
|
not evidence that all cleanup operations eventually succeeded.
|
|
305
314
|
|
|
306
|
-
## Packaging
|
|
307
|
-
|
|
308
|
-
`encore-dev` contains the Python SDK and is built with uv:
|
|
309
|
-
|
|
310
|
-
```sh
|
|
311
|
-
uv build sdk/py/infra
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
For release packaging, stage the SDK and stamp its version without changing the
|
|
315
|
-
checked-in manifest:
|
|
316
|
-
|
|
317
|
-
```sh
|
|
318
|
-
cargo xtask pack-python --version v2.0.0-alpha.1
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
This writes `encore_dev-2.0.0a1-py3-none-any.whl`, the source distribution, and
|
|
322
|
-
SHA-256 sidecars to `dist/python/` (override with `--output`). Alpha and beta
|
|
323
|
-
versions become `aN` and `bN`; nightly and development versions become `.devN`.
|
|
324
|
-
The command requires uv and the native build prerequisites (including Protoc).
|
|
325
|
-
It builds the native runtime to generate fresh type stubs, but packages only the
|
|
326
|
-
pure Python SDK and does not publish to PyPI.
|
|
327
|
-
|
|
328
|
-
The Rust extension lives in the parent `sdk/py/` directory and is packaged separately by Maturin.
|
|
329
|
-
Its `encore-runtime` wheel is an internal artifact for the CLI, not a dependency
|
|
330
|
-
of the public SDK:
|
|
331
|
-
|
|
332
|
-
```sh
|
|
333
|
-
# With Maturin installed:
|
|
334
|
-
cargo xtask build-py-runtime --release --wheel
|
|
335
|
-
# Optionally select the wheel's target (requires a suitable toolchain):
|
|
336
|
-
cargo xtask build-py-runtime --release --wheel --target aarch64-apple-darwin
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
SDK distributions are written to `sdk/py/infra/dist/`; native wheels go to
|
|
340
|
-
`sdk/py/dist/`.
|
|
341
|
-
|
|
342
|
-
## Building locally
|
|
343
|
-
|
|
344
|
-
From the repository root:
|
|
345
|
-
|
|
346
|
-
```sh
|
|
347
|
-
cargo xtask build-py-runtime
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
This stages `_encore_runtime` inside `infra/encore/` for the SDK's local loader,
|
|
351
|
-
and in `runtimes/python/` for the development CLI. It also regenerates
|
|
352
|
-
`encore/internal/_native.pyi` from the compiled extension. Edit native signatures
|
|
353
|
-
in Rust, then rerun this command to update the stub. An editable install of the SDK
|
|
354
|
-
can then load the native extension without setting `PYTHONPATH`:
|
|
355
|
-
|
|
356
|
-
```sh
|
|
357
|
-
uv run --project sdk/py/infra pytest sdk/py/infra/tests
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
The CLI sets `ENCORE_PYTHON_RUNTIME_DIR` for runs, tests, and exec commands.
|
|
361
|
-
The SDK selects the native library using the running interpreter's build ABI:
|
|
362
|
-
standard CPython uses the root `abi3` library; free-threaded Python 3.14 uses
|
|
363
|
-
`cp314t/_encore_runtime.so` (`.pyd` on Windows). This selection is unchanged if
|
|
364
|
-
a free-threaded interpreter temporarily enables its GIL. Unsupported ABIs fail
|
|
365
|
-
with a missing-runtime error instead of falling back to an incompatible library.
|
|
366
|
-
|
|
367
|
-
Build the local free-threaded variant separately:
|
|
368
|
-
|
|
369
|
-
```sh
|
|
370
|
-
cargo xtask build-py-runtime --python-runtime cp314t
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
The default builds `abi3`. Both variants can coexist. Native-only wheel builds
|
|
374
|
-
(`--wheel`) continue to use maturin's interpreter selection instead.
|
|
375
|
-
|
|
376
|
-
`ENCORE_PYTHON_RUNTIME_LIB` overrides directory selection with an explicit library.
|
|
377
|
-
An explicit library or directory is authoritative; failures do not fall back.
|
|
378
|
-
Without either variable, the loader searches beside itself and in parent
|
|
379
|
-
and `dist/` directories using the same ABI layout.
|
|
380
|
-
|
|
381
|
-
Configure the development CLI's `ENCORE_RUNTIMES_PATH` to point at this checkout's
|
|
382
|
-
`runtimes/` directory. Published SDK wheels exclude native libraries; standalone
|
|
383
|
-
use requires a runtime directory or explicit library from the CLI installation.
|
|
384
|
-
|
|
385
|
-
App builds install `encore-dev` and copy the runtime directory, preserving its ABI
|
|
386
|
-
variants for selection by the deployment interpreter. An explicit library override
|
|
387
|
-
is packaged separately and remains authoritative. Cross-platform runtime retrieval
|
|
388
|
-
is not yet supported.
|
|
389
|
-
|
|
390
315
|
## Resource initialization
|
|
391
316
|
|
|
392
|
-
Importing the SDK synchronously initializes the
|
|
393
|
-
TypeScript. Run applications through Encore so runtime configuration is available
|
|
317
|
+
Importing the SDK synchronously initializes the Encore runtime. Run applications through Encore so runtime configuration is available
|
|
394
318
|
before imports. Initialization failures surface during import, before normal
|
|
395
319
|
application startup completes.
|
|
396
320
|
|
|
@@ -398,39 +322,12 @@ Buckets, SQL databases, pub/sub topics, and secrets store their declarations and
|
|
|
398
322
|
resolve native handles on first use, caching the results with thread-safe
|
|
399
323
|
initialization. These lookups are synchronous against the already initialized
|
|
400
324
|
runtime. Importing application modules requires the configured runtime and native
|
|
401
|
-
extension.
|
|
402
|
-
|
|
325
|
+
extension. Use `encore test` to run application tests with Encore-managed
|
|
326
|
+
resources.
|
|
403
327
|
|
|
404
328
|
Initialize independently in each worker process. Forking an already initialized
|
|
405
329
|
native runtime is not supported by this startup model.
|
|
406
330
|
|
|
407
|
-
## Linting and formatting
|
|
408
|
-
|
|
409
|
-
From the repository root, lint the SDK and its tests:
|
|
410
|
-
|
|
411
|
-
```sh
|
|
412
|
-
uv run --locked --project sdk/py/infra ruff check sdk/py/infra
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
Add `--fix` to apply safe fixes. The enabled rules check syntax/style errors,
|
|
416
|
-
undefined and unused names, common bug patterns, and Google-style docstrings
|
|
417
|
-
(`E4`, `E7`, `E9`, `F`, `B`, `D`).
|
|
418
|
-
|
|
419
|
-
From the repository root, format the SDK and its tests with Ruff:
|
|
420
|
-
|
|
421
|
-
```sh
|
|
422
|
-
uv run --project sdk/py/infra ruff format sdk/py/infra
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
To check formatting without changing files:
|
|
426
|
-
|
|
427
|
-
```sh
|
|
428
|
-
uv run --project sdk/py/infra ruff format --check sdk/py/infra
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
The generated `_native.pyi` is excluded from linting and formatting because it
|
|
432
|
-
is owned by the PyO3 stub generator. It is still checked by ty.
|
|
433
|
-
|
|
434
331
|
## Metrics
|
|
435
332
|
|
|
436
333
|
Metrics are OpenTelemetry instruments of the meter `encore`, declared at module
|
|
@@ -483,63 +380,6 @@ trace.set_tracer_provider(tracer_provider())
|
|
|
483
380
|
metrics.set_meter_provider(meter_provider())
|
|
484
381
|
```
|
|
485
382
|
|
|
486
|
-
## Documentation style
|
|
487
|
-
|
|
488
|
-
Follow the [Google Python docstring guide](https://google.github.io/styleguide/pyguide.html#docstrings)
|
|
489
|
-
for modules, classes, functions, methods, and Python examples in documentation.
|
|
490
|
-
Start docstrings with a concise summary on the opening triple-double-quote line.
|
|
491
|
-
End the summary with punctuation, keep it within 80 characters, and separate any
|
|
492
|
-
further explanation with a blank line. Use imperative summaries for functions
|
|
493
|
-
("Return the current phase.") and noun phrases for classes and properties.
|
|
494
|
-
|
|
495
|
-
Use `Args:`, `Returns:`, `Yields:`, `Raises:`, and `Attributes:` as appropriate,
|
|
496
|
-
with four-space indentation for entries and continuation lines. Document behavior
|
|
497
|
-
callers need to know: units, defaults, side effects, resource ownership, and
|
|
498
|
-
relevant exceptions. Parameter names must match the signature, including `*args`
|
|
499
|
-
and `**kwargs`; type annotations usually make repeated type descriptions
|
|
500
|
-
unnecessary. Document public data attributes in the class's `Attributes:` section
|
|
501
|
-
and constructor arguments in `__init__`.
|
|
502
|
-
|
|
503
|
-
Simple APIs can use a one-line docstring when the summary and signature explain
|
|
504
|
-
their behavior completely. Omit `Returns:` for functions returning only `None`;
|
|
505
|
-
use `Yields:` for generators, describing each yielded item. For a decorated
|
|
506
|
-
context manager, describe the context manager returned to the caller. Put module
|
|
507
|
-
examples under `Typical usage example:`. Keep README prose and examples consistent
|
|
508
|
-
with these API contracts; Markdown guides retain their normal heading structure.
|
|
509
|
-
|
|
510
|
-
Ruff enforces the Google docstring convention through the existing lint command
|
|
511
|
-
and pre-commit hook. Test docstrings are optional; add them to explain unusual
|
|
512
|
-
setup or behavior rather than repeating test names. Existing test docstrings
|
|
513
|
-
still follow the same formatting rules. Review documentation for accuracy as
|
|
514
|
-
well as formatting: Ruff cannot verify behavioral contracts.
|
|
515
|
-
|
|
516
|
-
## Type checking
|
|
517
|
-
|
|
518
|
-
From the repository root, check the SDK, native stubs, and tests with ty:
|
|
519
|
-
|
|
520
|
-
```sh
|
|
521
|
-
uv run --project sdk/py/infra ty check --project sdk/py/infra
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
The checker uses the minimum Python version from `requires-python` and resolves
|
|
525
|
-
dependencies from the SDK's virtual environment.
|
|
526
|
-
|
|
527
|
-
## Pre-commit hooks
|
|
528
|
-
|
|
529
|
-
From the repository root, install the prek hooks once per checkout:
|
|
530
|
-
|
|
531
|
-
```sh
|
|
532
|
-
uv run --locked --project sdk/py/infra prek install
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
The hooks apply safe Ruff lint fixes, format the SDK, and check it with ty when
|
|
536
|
-
relevant SDK files change. If a hook changes files, stage those changes and commit
|
|
537
|
-
again. All hooks use the same locked tools as CI. To run them manually:
|
|
538
|
-
|
|
539
|
-
```sh
|
|
540
|
-
uv run --locked --project sdk/py/infra prek run --all-files
|
|
541
|
-
```
|
|
542
|
-
|
|
543
383
|
## Object storage
|
|
544
384
|
|
|
545
385
|
Declare a bucket at module scope, then use its async methods:
|
|
@@ -747,35 +587,3 @@ is cancelled.
|
|
|
747
587
|
`db.connection_string` (also available on write handles) returns the direct server
|
|
748
588
|
URL and grants broad read-write access. External clients using that URL do not
|
|
749
589
|
apply Encore's key prefixes or tracing. Read-only handles do not expose this URL.
|
|
750
|
-
|
|
751
|
-
## Testing Postgres
|
|
752
|
-
|
|
753
|
-
Build the native runtime from the repository root:
|
|
754
|
-
|
|
755
|
-
```sh
|
|
756
|
-
cargo xtask build-py-runtime
|
|
757
|
-
```
|
|
758
|
-
|
|
759
|
-
Then run the Postgres tests from `sdk/py/infra`:
|
|
760
|
-
|
|
761
|
-
```sh
|
|
762
|
-
uv sync --locked
|
|
763
|
-
uv run pytest tests/test_sqldb.py tests/test_postgres_runner.py -v
|
|
764
|
-
```
|
|
765
|
-
|
|
766
|
-
The integration runner starts one disposable `postgres:17` Docker container and
|
|
767
|
-
removes it after the suite. To use an existing test server, set
|
|
768
|
-
`ENCORE_PYTHON_POSTGRES_TEST_HOST=localhost:5432`. The server must provide a
|
|
769
|
-
`postgres` database and user with password `encore-test` and schema creation
|
|
770
|
-
privileges. Use a dedicated test server.
|
|
771
|
-
|
|
772
|
-
`tests/test_postgres_runner.py` launches `tests/postgres_integration_suite.py`
|
|
773
|
-
in a separate process to isolate the native runtime configuration. The suite is
|
|
774
|
-
collected explicitly by the runner and excluded from normal pytest discovery
|
|
775
|
-
by its filename.
|
|
776
|
-
Each test and Hypothesis example gets a fresh schema. The suite includes
|
|
777
|
-
parameter round trips, generated transaction and cursor operation sequences,
|
|
778
|
-
and synchronized cancellation regressions. Hypothesis uses deterministic generation and reports minimized failing examples.
|
|
779
|
-
Sequences are repeatable for unchanged tests and the same Hypothesis version.
|
|
780
|
-
Resource cleanup and bounded polling live in `tests/postgres_test_support.py`.
|
|
781
|
-
These integration tests are run locally and are not executed by CI.
|
|
@@ -2,16 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
The Python SDK for [Encore](https://encore.dev) — **infrastructure resources only**.
|
|
4
4
|
|
|
5
|
-
The distribution is named `encore-dev`; Python code imports it as `encore`.
|
|
6
|
-
|
|
7
5
|
Declare infrastructure (SQL databases, pub/sub topics & subscriptions, object
|
|
8
6
|
storage buckets, Redis databases, cron jobs, metrics, secrets) as module-level variables.
|
|
9
|
-
Encore
|
|
10
|
-
|
|
11
|
-
infrastructure at run time.
|
|
7
|
+
Encore discovers these declarations, provisions the resources, and connects your
|
|
8
|
+
application to them at runtime.
|
|
12
9
|
|
|
13
10
|
Services are declared by the language-agnostic `encore.service.json` file, not in
|
|
14
|
-
Python
|
|
11
|
+
Python. Use the SDK with your preferred Python web framework.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Requires Python 3.9 or later. Install from PyPI with pip:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
python -m pip install encore-dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or add it to a uv project:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
uv add encore-dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Declare resources
|
|
15
28
|
|
|
16
29
|
```python
|
|
17
30
|
from encore import pubsub, secrets
|
|
@@ -52,7 +65,8 @@ Declare `postgres.Database("orders", migrations="./migrations")` at module scope
|
|
|
52
65
|
reference a database declared elsewhere.
|
|
53
66
|
|
|
54
67
|
`query(sql, *params)` returns a `Cursor`. Use `async for` to stream rows,
|
|
55
|
-
`await query.one()` to fetch one row
|
|
68
|
+
`await query.one()` to fetch exactly one row (raising `EncoreError` on no rows or
|
|
69
|
+
more than one), `await query.first()` to fetch the first row or `None`, or
|
|
56
70
|
`await query.all()` to collect all rows in a list. Each query can be consumed
|
|
57
71
|
once. Reusing it or mixing helpers with iteration raises `EncoreError`, including
|
|
58
72
|
after partial iteration or an error. Helpers close their cursors automatically.
|
|
@@ -64,7 +78,7 @@ dictionaries keyed by column name. Values are bound with `$1`, `$2`, etc.
|
|
|
64
78
|
|
|
65
79
|
```python
|
|
66
80
|
async def find_order(database: postgres.Queryable, order_id: int):
|
|
67
|
-
return await database.query("SELECT * FROM orders WHERE id = $1", order_id).
|
|
81
|
+
return await database.query("SELECT * FROM orders WHERE id = $1", order_id).first()
|
|
68
82
|
|
|
69
83
|
|
|
70
84
|
async def handle_order(order_id: int):
|
|
@@ -78,7 +92,7 @@ select `read()`, `write()`, or `admin()` before handing it to another function.
|
|
|
78
92
|
Direct database operations infer writer permissions. Reference creation records
|
|
79
93
|
reader, writer, or admin permissions at that call site.
|
|
80
94
|
|
|
81
|
-
|
|
95
|
+
Handles share the database's pool. A `read()` handle runs on
|
|
82
96
|
read-only connections, so its writes fail with SQLSTATE 25006 and its
|
|
83
97
|
transactions are read-only; it reads from the database's read-only pool on a
|
|
84
98
|
replica if the runtime config has one, unless `primary=True` is set.
|
|
@@ -109,11 +123,6 @@ async def first_order():
|
|
|
109
123
|
return row
|
|
110
124
|
```
|
|
111
125
|
|
|
112
|
-
Native Postgres integration tests can be enabled with
|
|
113
|
-
`ENCORE_PYTHON_POSTGRES_TEST_HOST=host:port`. They expect an isolated Postgres
|
|
114
|
-
instance with database/user `postgres` and password `encore-test`, and create and
|
|
115
|
-
remove a temporary schema.
|
|
116
|
-
|
|
117
126
|
## Pub/Sub payloads
|
|
118
127
|
|
|
119
128
|
Use `pubsub.Subscription[T]` to choose how payloads are decoded. Encore validates
|
|
@@ -290,94 +299,9 @@ If cleanup panics after the deadline has already recorded `Timeout`, the core
|
|
|
290
299
|
logs the failure and preserves `Timeout` as the reported result. A timeout is
|
|
291
300
|
not evidence that all cleanup operations eventually succeeded.
|
|
292
301
|
|
|
293
|
-
## Packaging
|
|
294
|
-
|
|
295
|
-
`encore-dev` contains the Python SDK and is built with uv:
|
|
296
|
-
|
|
297
|
-
```sh
|
|
298
|
-
uv build sdk/py/infra
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
For release packaging, stage the SDK and stamp its version without changing the
|
|
302
|
-
checked-in manifest:
|
|
303
|
-
|
|
304
|
-
```sh
|
|
305
|
-
cargo xtask pack-python --version v2.0.0-alpha.1
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
This writes `encore_dev-2.0.0a1-py3-none-any.whl`, the source distribution, and
|
|
309
|
-
SHA-256 sidecars to `dist/python/` (override with `--output`). Alpha and beta
|
|
310
|
-
versions become `aN` and `bN`; nightly and development versions become `.devN`.
|
|
311
|
-
The command requires uv and the native build prerequisites (including Protoc).
|
|
312
|
-
It builds the native runtime to generate fresh type stubs, but packages only the
|
|
313
|
-
pure Python SDK and does not publish to PyPI.
|
|
314
|
-
|
|
315
|
-
The Rust extension lives in the parent `sdk/py/` directory and is packaged separately by Maturin.
|
|
316
|
-
Its `encore-runtime` wheel is an internal artifact for the CLI, not a dependency
|
|
317
|
-
of the public SDK:
|
|
318
|
-
|
|
319
|
-
```sh
|
|
320
|
-
# With Maturin installed:
|
|
321
|
-
cargo xtask build-py-runtime --release --wheel
|
|
322
|
-
# Optionally select the wheel's target (requires a suitable toolchain):
|
|
323
|
-
cargo xtask build-py-runtime --release --wheel --target aarch64-apple-darwin
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
SDK distributions are written to `sdk/py/infra/dist/`; native wheels go to
|
|
327
|
-
`sdk/py/dist/`.
|
|
328
|
-
|
|
329
|
-
## Building locally
|
|
330
|
-
|
|
331
|
-
From the repository root:
|
|
332
|
-
|
|
333
|
-
```sh
|
|
334
|
-
cargo xtask build-py-runtime
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
This stages `_encore_runtime` inside `infra/encore/` for the SDK's local loader,
|
|
338
|
-
and in `runtimes/python/` for the development CLI. It also regenerates
|
|
339
|
-
`encore/internal/_native.pyi` from the compiled extension. Edit native signatures
|
|
340
|
-
in Rust, then rerun this command to update the stub. An editable install of the SDK
|
|
341
|
-
can then load the native extension without setting `PYTHONPATH`:
|
|
342
|
-
|
|
343
|
-
```sh
|
|
344
|
-
uv run --project sdk/py/infra pytest sdk/py/infra/tests
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
The CLI sets `ENCORE_PYTHON_RUNTIME_DIR` for runs, tests, and exec commands.
|
|
348
|
-
The SDK selects the native library using the running interpreter's build ABI:
|
|
349
|
-
standard CPython uses the root `abi3` library; free-threaded Python 3.14 uses
|
|
350
|
-
`cp314t/_encore_runtime.so` (`.pyd` on Windows). This selection is unchanged if
|
|
351
|
-
a free-threaded interpreter temporarily enables its GIL. Unsupported ABIs fail
|
|
352
|
-
with a missing-runtime error instead of falling back to an incompatible library.
|
|
353
|
-
|
|
354
|
-
Build the local free-threaded variant separately:
|
|
355
|
-
|
|
356
|
-
```sh
|
|
357
|
-
cargo xtask build-py-runtime --python-runtime cp314t
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
The default builds `abi3`. Both variants can coexist. Native-only wheel builds
|
|
361
|
-
(`--wheel`) continue to use maturin's interpreter selection instead.
|
|
362
|
-
|
|
363
|
-
`ENCORE_PYTHON_RUNTIME_LIB` overrides directory selection with an explicit library.
|
|
364
|
-
An explicit library or directory is authoritative; failures do not fall back.
|
|
365
|
-
Without either variable, the loader searches beside itself and in parent
|
|
366
|
-
and `dist/` directories using the same ABI layout.
|
|
367
|
-
|
|
368
|
-
Configure the development CLI's `ENCORE_RUNTIMES_PATH` to point at this checkout's
|
|
369
|
-
`runtimes/` directory. Published SDK wheels exclude native libraries; standalone
|
|
370
|
-
use requires a runtime directory or explicit library from the CLI installation.
|
|
371
|
-
|
|
372
|
-
App builds install `encore-dev` and copy the runtime directory, preserving its ABI
|
|
373
|
-
variants for selection by the deployment interpreter. An explicit library override
|
|
374
|
-
is packaged separately and remains authoritative. Cross-platform runtime retrieval
|
|
375
|
-
is not yet supported.
|
|
376
|
-
|
|
377
302
|
## Resource initialization
|
|
378
303
|
|
|
379
|
-
Importing the SDK synchronously initializes the
|
|
380
|
-
TypeScript. Run applications through Encore so runtime configuration is available
|
|
304
|
+
Importing the SDK synchronously initializes the Encore runtime. Run applications through Encore so runtime configuration is available
|
|
381
305
|
before imports. Initialization failures surface during import, before normal
|
|
382
306
|
application startup completes.
|
|
383
307
|
|
|
@@ -385,39 +309,12 @@ Buckets, SQL databases, pub/sub topics, and secrets store their declarations and
|
|
|
385
309
|
resolve native handles on first use, caching the results with thread-safe
|
|
386
310
|
initialization. These lookups are synchronous against the already initialized
|
|
387
311
|
runtime. Importing application modules requires the configured runtime and native
|
|
388
|
-
extension.
|
|
389
|
-
|
|
312
|
+
extension. Use `encore test` to run application tests with Encore-managed
|
|
313
|
+
resources.
|
|
390
314
|
|
|
391
315
|
Initialize independently in each worker process. Forking an already initialized
|
|
392
316
|
native runtime is not supported by this startup model.
|
|
393
317
|
|
|
394
|
-
## Linting and formatting
|
|
395
|
-
|
|
396
|
-
From the repository root, lint the SDK and its tests:
|
|
397
|
-
|
|
398
|
-
```sh
|
|
399
|
-
uv run --locked --project sdk/py/infra ruff check sdk/py/infra
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
Add `--fix` to apply safe fixes. The enabled rules check syntax/style errors,
|
|
403
|
-
undefined and unused names, common bug patterns, and Google-style docstrings
|
|
404
|
-
(`E4`, `E7`, `E9`, `F`, `B`, `D`).
|
|
405
|
-
|
|
406
|
-
From the repository root, format the SDK and its tests with Ruff:
|
|
407
|
-
|
|
408
|
-
```sh
|
|
409
|
-
uv run --project sdk/py/infra ruff format sdk/py/infra
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
To check formatting without changing files:
|
|
413
|
-
|
|
414
|
-
```sh
|
|
415
|
-
uv run --project sdk/py/infra ruff format --check sdk/py/infra
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
The generated `_native.pyi` is excluded from linting and formatting because it
|
|
419
|
-
is owned by the PyO3 stub generator. It is still checked by ty.
|
|
420
|
-
|
|
421
318
|
## Metrics
|
|
422
319
|
|
|
423
320
|
Metrics are OpenTelemetry instruments of the meter `encore`, declared at module
|
|
@@ -470,63 +367,6 @@ trace.set_tracer_provider(tracer_provider())
|
|
|
470
367
|
metrics.set_meter_provider(meter_provider())
|
|
471
368
|
```
|
|
472
369
|
|
|
473
|
-
## Documentation style
|
|
474
|
-
|
|
475
|
-
Follow the [Google Python docstring guide](https://google.github.io/styleguide/pyguide.html#docstrings)
|
|
476
|
-
for modules, classes, functions, methods, and Python examples in documentation.
|
|
477
|
-
Start docstrings with a concise summary on the opening triple-double-quote line.
|
|
478
|
-
End the summary with punctuation, keep it within 80 characters, and separate any
|
|
479
|
-
further explanation with a blank line. Use imperative summaries for functions
|
|
480
|
-
("Return the current phase.") and noun phrases for classes and properties.
|
|
481
|
-
|
|
482
|
-
Use `Args:`, `Returns:`, `Yields:`, `Raises:`, and `Attributes:` as appropriate,
|
|
483
|
-
with four-space indentation for entries and continuation lines. Document behavior
|
|
484
|
-
callers need to know: units, defaults, side effects, resource ownership, and
|
|
485
|
-
relevant exceptions. Parameter names must match the signature, including `*args`
|
|
486
|
-
and `**kwargs`; type annotations usually make repeated type descriptions
|
|
487
|
-
unnecessary. Document public data attributes in the class's `Attributes:` section
|
|
488
|
-
and constructor arguments in `__init__`.
|
|
489
|
-
|
|
490
|
-
Simple APIs can use a one-line docstring when the summary and signature explain
|
|
491
|
-
their behavior completely. Omit `Returns:` for functions returning only `None`;
|
|
492
|
-
use `Yields:` for generators, describing each yielded item. For a decorated
|
|
493
|
-
context manager, describe the context manager returned to the caller. Put module
|
|
494
|
-
examples under `Typical usage example:`. Keep README prose and examples consistent
|
|
495
|
-
with these API contracts; Markdown guides retain their normal heading structure.
|
|
496
|
-
|
|
497
|
-
Ruff enforces the Google docstring convention through the existing lint command
|
|
498
|
-
and pre-commit hook. Test docstrings are optional; add them to explain unusual
|
|
499
|
-
setup or behavior rather than repeating test names. Existing test docstrings
|
|
500
|
-
still follow the same formatting rules. Review documentation for accuracy as
|
|
501
|
-
well as formatting: Ruff cannot verify behavioral contracts.
|
|
502
|
-
|
|
503
|
-
## Type checking
|
|
504
|
-
|
|
505
|
-
From the repository root, check the SDK, native stubs, and tests with ty:
|
|
506
|
-
|
|
507
|
-
```sh
|
|
508
|
-
uv run --project sdk/py/infra ty check --project sdk/py/infra
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
The checker uses the minimum Python version from `requires-python` and resolves
|
|
512
|
-
dependencies from the SDK's virtual environment.
|
|
513
|
-
|
|
514
|
-
## Pre-commit hooks
|
|
515
|
-
|
|
516
|
-
From the repository root, install the prek hooks once per checkout:
|
|
517
|
-
|
|
518
|
-
```sh
|
|
519
|
-
uv run --locked --project sdk/py/infra prek install
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
The hooks apply safe Ruff lint fixes, format the SDK, and check it with ty when
|
|
523
|
-
relevant SDK files change. If a hook changes files, stage those changes and commit
|
|
524
|
-
again. All hooks use the same locked tools as CI. To run them manually:
|
|
525
|
-
|
|
526
|
-
```sh
|
|
527
|
-
uv run --locked --project sdk/py/infra prek run --all-files
|
|
528
|
-
```
|
|
529
|
-
|
|
530
370
|
## Object storage
|
|
531
371
|
|
|
532
372
|
Declare a bucket at module scope, then use its async methods:
|
|
@@ -734,35 +574,3 @@ is cancelled.
|
|
|
734
574
|
`db.connection_string` (also available on write handles) returns the direct server
|
|
735
575
|
URL and grants broad read-write access. External clients using that URL do not
|
|
736
576
|
apply Encore's key prefixes or tracing. Read-only handles do not expose this URL.
|
|
737
|
-
|
|
738
|
-
## Testing Postgres
|
|
739
|
-
|
|
740
|
-
Build the native runtime from the repository root:
|
|
741
|
-
|
|
742
|
-
```sh
|
|
743
|
-
cargo xtask build-py-runtime
|
|
744
|
-
```
|
|
745
|
-
|
|
746
|
-
Then run the Postgres tests from `sdk/py/infra`:
|
|
747
|
-
|
|
748
|
-
```sh
|
|
749
|
-
uv sync --locked
|
|
750
|
-
uv run pytest tests/test_sqldb.py tests/test_postgres_runner.py -v
|
|
751
|
-
```
|
|
752
|
-
|
|
753
|
-
The integration runner starts one disposable `postgres:17` Docker container and
|
|
754
|
-
removes it after the suite. To use an existing test server, set
|
|
755
|
-
`ENCORE_PYTHON_POSTGRES_TEST_HOST=localhost:5432`. The server must provide a
|
|
756
|
-
`postgres` database and user with password `encore-test` and schema creation
|
|
757
|
-
privileges. Use a dedicated test server.
|
|
758
|
-
|
|
759
|
-
`tests/test_postgres_runner.py` launches `tests/postgres_integration_suite.py`
|
|
760
|
-
in a separate process to isolate the native runtime configuration. The suite is
|
|
761
|
-
collected explicitly by the runner and excluded from normal pytest discovery
|
|
762
|
-
by its filename.
|
|
763
|
-
Each test and Hypothesis example gets a fresh schema. The suite includes
|
|
764
|
-
parameter round trips, generated transaction and cursor operation sequences,
|
|
765
|
-
and synchronized cancellation regressions. Hypothesis uses deterministic generation and reports minimized failing examples.
|
|
766
|
-
Sequences are repeatable for unchanged tests and the same Hypothesis version.
|
|
767
|
-
Resource cleanup and bounded polling live in `tests/postgres_test_support.py`.
|
|
768
|
-
These integration tests are run locally and are not executed by CI.
|
|
@@ -59,7 +59,7 @@ Changes:
|
|
|
59
59
|
Files:
|
|
60
60
|
A config's value is written in a file named after it,
|
|
61
61
|
``checkout.config.toml`` (or ``.json``), beside the declaring service's
|
|
62
|
-
``encore.service.json``, or beside ``encore.app`` for a shared or global
|
|
62
|
+
``encore.service.json``, or beside ``encore.app.json`` for a shared or global
|
|
63
63
|
config. Overlays change it for some environments only:
|
|
64
64
|
``checkout.production.config.toml`` for an environment type,
|
|
65
65
|
``checkout.@prod-eu.config.toml`` for one environment, and
|
|
@@ -53,7 +53,7 @@ class ExecResult:
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
class Cursor:
|
|
56
|
-
"""A SQL cursor consumed once by iteration, one(), or all().
|
|
56
|
+
"""A SQL cursor consumed once by iteration, one(), first(), or all().
|
|
57
57
|
|
|
58
58
|
Execution starts when iteration advances or a helper is awaited. Starting
|
|
59
59
|
one consumption mode prevents any other consumption of this query, including
|
|
@@ -62,8 +62,8 @@ class Cursor:
|
|
|
62
62
|
|
|
63
63
|
Exhaust a stream or call aclose() to release its connection. For early exits,
|
|
64
64
|
use the query as an async context manager. Entering the context does not
|
|
65
|
-
execute or consume the query. Leaving it closes the stream. The one()
|
|
66
|
-
all() helpers close their cursors automatically.
|
|
65
|
+
execute or consume the query. Leaving it closes the stream. The one(),
|
|
66
|
+
first(), and all() helpers close their cursors automatically.
|
|
67
67
|
"""
|
|
68
68
|
|
|
69
69
|
def __init__(self, rows: AsyncGenerator[Row, None]) -> None:
|
|
@@ -89,23 +89,47 @@ class Cursor:
|
|
|
89
89
|
"""
|
|
90
90
|
return self._consume()
|
|
91
91
|
|
|
92
|
-
async def one(self) -> Row
|
|
93
|
-
"""Return
|
|
92
|
+
async def one(self) -> Row:
|
|
93
|
+
"""Return the query's only row and close the cursor.
|
|
94
|
+
|
|
95
|
+
Use first() when the query may match no rows.
|
|
94
96
|
|
|
95
97
|
Returns:
|
|
96
|
-
A dictionary of column names to values
|
|
98
|
+
A dictionary of column names to values.
|
|
97
99
|
|
|
98
100
|
Raises:
|
|
99
|
-
EncoreError: The query fails or returns more than
|
|
101
|
+
EncoreError: The query fails, returns no rows, or returns more than
|
|
102
|
+
one row.
|
|
100
103
|
"""
|
|
101
104
|
rows = self._consume()
|
|
102
105
|
try:
|
|
103
|
-
|
|
106
|
+
found = None
|
|
104
107
|
async for row in rows:
|
|
105
|
-
if
|
|
108
|
+
if found is not None:
|
|
106
109
|
raise EncoreError("query returned more than one row")
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
found = row
|
|
111
|
+
if found is None:
|
|
112
|
+
raise EncoreError("query returned no rows")
|
|
113
|
+
return found
|
|
114
|
+
finally:
|
|
115
|
+
await rows.aclose()
|
|
116
|
+
|
|
117
|
+
async def first(self) -> Row | None:
|
|
118
|
+
"""Return the query's first row, if any, and close the cursor.
|
|
119
|
+
|
|
120
|
+
Rows after the first are not read.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
A dictionary of column names to values, or None if no rows match.
|
|
124
|
+
|
|
125
|
+
Raises:
|
|
126
|
+
EncoreError: The query fails.
|
|
127
|
+
"""
|
|
128
|
+
rows = self._consume()
|
|
129
|
+
try:
|
|
130
|
+
async for row in rows:
|
|
131
|
+
return row
|
|
132
|
+
return None
|
|
109
133
|
finally:
|
|
110
134
|
await rows.aclose()
|
|
111
135
|
|
|
@@ -231,9 +255,9 @@ class Queryable:
|
|
|
231
255
|
def query(self, sql: str, *params: Any) -> Cursor:
|
|
232
256
|
"""Create a query for streaming or fetching rows.
|
|
233
257
|
|
|
234
|
-
Consume the query once with async iteration, one(), or all().
|
|
235
|
-
until iteration advances or a helper is awaited. Exhaust the
|
|
236
|
-
close it before reusing its connection or transaction. Use
|
|
258
|
+
Consume the query once with async iteration, one(), first(), or all().
|
|
259
|
+
No SQL runs until iteration advances or a helper is awaited. Exhaust the
|
|
260
|
+
stream or close it before reusing its connection or transaction. Use
|
|
237
261
|
the query as an async context manager when leaving iteration early.
|
|
238
262
|
|
|
239
263
|
Args:
|
|
@@ -445,9 +469,9 @@ class Database:
|
|
|
445
469
|
def query(self, sql: str, *params: Any) -> Cursor:
|
|
446
470
|
"""Create a query for streaming or fetching rows.
|
|
447
471
|
|
|
448
|
-
Consume the query once with async iteration, one(), or all().
|
|
449
|
-
until iteration advances or a helper is awaited. See
|
|
450
|
-
for stream cleanup requirements.
|
|
472
|
+
Consume the query once with async iteration, one(), first(), or all().
|
|
473
|
+
No SQL runs until iteration advances or a helper is awaited. See
|
|
474
|
+
Queryable.query for stream cleanup requirements.
|
|
451
475
|
|
|
452
476
|
Args:
|
|
453
477
|
sql: A SQL statement with positional placeholders such as $1 and $2.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|