encore-dev 2.0.0a16__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.
Files changed (52) hide show
  1. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/PKG-INFO +4 -3
  2. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/README.md +3 -2
  3. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/postgres/__init__.py +41 -17
  4. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/pyproject.toml +1 -1
  5. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/pyproject.toml.orig +1 -1
  6. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/__init__.py +0 -0
  7. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/config/__init__.py +0 -0
  8. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/config/_build.py +0 -0
  9. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/config/_markers.py +0 -0
  10. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/cron/__init__.py +0 -0
  11. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/env/__init__.py +0 -0
  12. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/__init__.py +0 -0
  13. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/_loader.py +0 -0
  14. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/_native.pyi +0 -0
  15. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/lazy.py +0 -0
  16. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/runtime.py +0 -0
  17. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/internal/startup.py +0 -0
  18. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/logs/__init__.py +0 -0
  19. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/logs/_console.py +0 -0
  20. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/logs/_runtime.py +0 -0
  21. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/metrics/__init__.py +0 -0
  22. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/metrics/_instrument.py +0 -0
  23. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/metrics/_metrics.py +0 -0
  24. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/metrics/_provider.py +0 -0
  25. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/pubsub/__init__.py +0 -0
  26. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/py.typed +0 -0
  27. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/secrets/__init__.py +0 -0
  28. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/services/__init__.py +0 -0
  29. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/shutdown/__init__.py +0 -0
  30. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/__init__.py +0 -0
  31. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/objects/__init__.py +0 -0
  32. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/__init__.py +0 -0
  33. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/_base.py +0 -0
  34. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/_responses.py +0 -0
  35. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/_values.py +0 -0
  36. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/bitmap.py +0 -0
  37. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/generic.py +0 -0
  38. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/geo.py +0 -0
  39. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/hash.py +0 -0
  40. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/json.py +0 -0
  41. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/list.py +0 -0
  42. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/pubsub.py +0 -0
  43. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/set.py +0 -0
  44. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/sorted_set.py +0 -0
  45. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/stream.py +0 -0
  46. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/storage/redis/string.py +0 -0
  47. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/tracing/__init__.py +0 -0
  48. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/tracing/_context.py +0 -0
  49. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/tracing/_encode.py +0 -0
  50. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/tracing/_provider.py +0 -0
  51. {encore_dev-2.0.0a16 → encore_dev-2.0.0a17}/encore/tracing/_span.py +0 -0
  52. {encore_dev-2.0.0a16 → 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.0a16
3
+ Version: 2.0.0a17
4
4
  Summary: Encore SDK for Python — infrastructure resources
5
5
  Author: Encore
6
6
  License: MPL-2.0
@@ -78,7 +78,8 @@ Declare `postgres.Database("orders", migrations="./migrations")` at module scope
78
78
  reference a database declared elsewhere.
79
79
 
80
80
  `query(sql, *params)` returns a `Cursor`. Use `async for` to stream rows,
81
- `await query.one()` to fetch one row or `None` (rejecting multiple rows), or
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
82
83
  `await query.all()` to collect all rows in a list. Each query can be consumed
83
84
  once. Reusing it or mixing helpers with iteration raises `EncoreError`, including
84
85
  after partial iteration or an error. Helpers close their cursors automatically.
@@ -90,7 +91,7 @@ dictionaries keyed by column name. Values are bound with `$1`, `$2`, etc.
90
91
 
91
92
  ```python
92
93
  async def find_order(database: postgres.Queryable, order_id: int):
93
- return await database.query("SELECT * FROM orders WHERE id = $1", order_id).one()
94
+ return await database.query("SELECT * FROM orders WHERE id = $1", order_id).first()
94
95
 
95
96
 
96
97
  async def handle_order(order_id: int):
@@ -65,7 +65,8 @@ Declare `postgres.Database("orders", migrations="./migrations")` at module scope
65
65
  reference a database declared elsewhere.
66
66
 
67
67
  `query(sql, *params)` returns a `Cursor`. Use `async for` to stream rows,
68
- `await query.one()` to fetch one row or `None` (rejecting multiple rows), or
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
69
70
  `await query.all()` to collect all rows in a list. Each query can be consumed
70
71
  once. Reusing it or mixing helpers with iteration raises `EncoreError`, including
71
72
  after partial iteration or an error. Helpers close their cursors automatically.
@@ -77,7 +78,7 @@ dictionaries keyed by column name. Values are bound with `$1`, `$2`, etc.
77
78
 
78
79
  ```python
79
80
  async def find_order(database: postgres.Queryable, order_id: int):
80
- return await database.query("SELECT * FROM orders WHERE id = $1", order_id).one()
81
+ return await database.query("SELECT * FROM orders WHERE id = $1", order_id).first()
81
82
 
82
83
 
83
84
  async def handle_order(order_id: int):
@@ -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() and
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 | None:
93
- """Return zero or one row and close the cursor.
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, or None if no rows match.
98
+ A dictionary of column names to values.
97
99
 
98
100
  Raises:
99
- EncoreError: The query fails or returns more than one row.
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
- first = None
106
+ found = None
104
107
  async for row in rows:
105
- if first is not None:
108
+ if found is not None:
106
109
  raise EncoreError("query returned more than one row")
107
- first = row
108
- return first
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(). No SQL runs
235
- until iteration advances or a helper is awaited. Exhaust the stream or
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(). No SQL runs
449
- until iteration advances or a helper is awaited. See Queryable.query
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.
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "encore-dev"
7
- version = "2.0.0a16"
7
+ version = "2.0.0a17"
8
8
  description = "Encore SDK for Python — infrastructure resources"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "encore-dev"
7
- version = "2.0.0a16"
7
+ version = "2.0.0a17"
8
8
  description = "Encore SDK for Python — infrastructure resources"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"