encore-dev 2.0.0a7__py3-none-any.whl

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 (44) hide show
  1. encore/__init__.py +43 -0
  2. encore/cron/__init__.py +50 -0
  3. encore/internal/__init__.py +1 -0
  4. encore/internal/_loader.py +79 -0
  5. encore/internal/_native.pyi +734 -0
  6. encore/internal/lazy.py +35 -0
  7. encore/internal/runtime.py +133 -0
  8. encore/internal/startup.py +24 -0
  9. encore/logs/__init__.py +19 -0
  10. encore/logs/_console.py +155 -0
  11. encore/logs/_runtime.py +56 -0
  12. encore/meta/__init__.py +228 -0
  13. encore/metrics/__init__.py +390 -0
  14. encore/pubsub/__init__.py +425 -0
  15. encore/py.typed +0 -0
  16. encore/secrets/__init__.py +139 -0
  17. encore/shutdown/__init__.py +164 -0
  18. encore/storage/__init__.py +5 -0
  19. encore/storage/objects/__init__.py +396 -0
  20. encore/storage/postgres/__init__.py +737 -0
  21. encore/storage/redis/__init__.py +200 -0
  22. encore/storage/redis/_base.py +42 -0
  23. encore/storage/redis/_responses.py +150 -0
  24. encore/storage/redis/_values.py +189 -0
  25. encore/storage/redis/bitmap.py +142 -0
  26. encore/storage/redis/generic.py +367 -0
  27. encore/storage/redis/geo.py +508 -0
  28. encore/storage/redis/hash.py +504 -0
  29. encore/storage/redis/json.py +614 -0
  30. encore/storage/redis/list.py +511 -0
  31. encore/storage/redis/pubsub.py +276 -0
  32. encore/storage/redis/set.py +570 -0
  33. encore/storage/redis/sorted_set.py +753 -0
  34. encore/storage/redis/stream.py +773 -0
  35. encore/storage/redis/string.py +654 -0
  36. encore/tracing/__init__.py +19 -0
  37. encore/tracing/_context.py +27 -0
  38. encore/tracing/_encode.py +351 -0
  39. encore/tracing/_provider.py +62 -0
  40. encore/tracing/_span.py +226 -0
  41. encore/tracing/_tracer.py +93 -0
  42. encore_dev-2.0.0a7.dist-info/METADATA +791 -0
  43. encore_dev-2.0.0a7.dist-info/RECORD +44 -0
  44. encore_dev-2.0.0a7.dist-info/WHEEL +4 -0
@@ -0,0 +1,511 @@
1
+ """Redis list commands.
2
+
3
+ Keys are strings without Encore prefixes. Values accept bytes, str, int, float,
4
+ or
5
+ RedisValue implementations; value reads default to bytes. Use command[T](...) to
6
+ decode values as T. Custom encoding and decoding errors propagate to the caller.
7
+ Repeated arguments are variadic. Individual commands document their reply
8
+ shapes and any option-dependent behavior.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Optional
14
+
15
+ from ...tracing._context import active_ctx_bytes
16
+ from ._base import CommandInterface, TypedCommand
17
+ from ._values import T, Value, encode, decode, decode_optional, decode_pop, U
18
+
19
+
20
+ class _LindexCommand(TypedCommand[T]):
21
+ """A callable LINDEX command with selectable value decoding."""
22
+
23
+ def __getitem__(self, value_type: type[U]) -> _LindexCommand[U]:
24
+ """Select the value type for this command.
25
+
26
+ Use lindex[T](...) to decode stored values as T. Selecting a type does
27
+ not open a connection or change the decoder of an existing command.
28
+
29
+ Args:
30
+ value_type: bytes, str, int, float, or a class implementing
31
+ RedisValue.
32
+
33
+ Returns:
34
+ An independent command with the same arguments and the selected
35
+ decoder. Keys and other command metadata retain their existing
36
+ types.
37
+ """
38
+ return _LindexCommand(self._get_handle, value_type)
39
+
40
+ async def __call__(self, key: str, index: int) -> Optional[T]:
41
+ """Return the element at a list index.
42
+
43
+ Args:
44
+ key: The database key, without an Encore key prefix.
45
+ index: The zero-based index; negative values count from the end.
46
+
47
+ Returns:
48
+ The decoded element, or None if the key or index does not exist.
49
+
50
+ Raises:
51
+ UnicodeDecodeError: A value is not valid UTF-8 when the type
52
+ argument is str.
53
+ ValueError: A stored value cannot be parsed as int or float.
54
+ EncoreError: Redis rejects the command or the request fails.
55
+ """
56
+ result = await self._get_handle().list_lindex(
57
+ key, index, source=active_ctx_bytes()
58
+ )
59
+ return decode_optional(result, self._value_type)
60
+
61
+
62
+ class _LrangeCommand(TypedCommand[T]):
63
+ """A callable LRANGE command with selectable value decoding."""
64
+
65
+ def __getitem__(self, value_type: type[U]) -> _LrangeCommand[U]:
66
+ """Select the value type for this command.
67
+
68
+ Use lrange[T](...) to decode stored values as T. Selecting a type does
69
+ not open a connection or change the decoder of an existing command.
70
+
71
+ Args:
72
+ value_type: bytes, str, int, float, or a class implementing
73
+ RedisValue.
74
+
75
+ Returns:
76
+ An independent command with the same arguments and the selected
77
+ decoder. Keys and other command metadata retain their existing
78
+ types.
79
+ """
80
+ return _LrangeCommand(self._get_handle, value_type)
81
+
82
+ async def __call__(self, key: str, start: int, stop: int) -> list[T]:
83
+ """Return an inclusive range of list elements.
84
+
85
+ Args:
86
+ key: The database key, without an Encore key prefix.
87
+ start: The inclusive starting index; negative values count from the
88
+ end.
89
+ stop: The inclusive ending index; negative values count from the
90
+ end.
91
+
92
+ Returns:
93
+ Elements in list order; empty if the key or range is empty.
94
+
95
+ Raises:
96
+ UnicodeDecodeError: A value is not valid UTF-8 when the type
97
+ argument is str.
98
+ ValueError: A stored value cannot be parsed as int or float.
99
+ EncoreError: Redis rejects the command or the request fails.
100
+ """
101
+ result = await self._get_handle().list_lrange(
102
+ key, start, stop, source=active_ctx_bytes()
103
+ )
104
+ return [decode(value, self._value_type) for value in result]
105
+
106
+
107
+ class _LmoveCommand(TypedCommand[T]):
108
+ """A callable LMOVE command with selectable value decoding."""
109
+
110
+ def __getitem__(self, value_type: type[U]) -> _LmoveCommand[U]:
111
+ """Select the value type for this command.
112
+
113
+ Use lmove[T](...) to decode stored values as T. Selecting a type does
114
+ not open a connection or change the decoder of an existing command.
115
+
116
+ Args:
117
+ value_type: bytes, str, int, float, or a class implementing
118
+ RedisValue.
119
+
120
+ Returns:
121
+ An independent command with the same arguments and the selected
122
+ decoder. Keys and other command metadata retain their existing
123
+ types.
124
+ """
125
+ return _LmoveCommand(self._get_handle, value_type)
126
+
127
+ async def __call__(
128
+ self, key: str, destination: str, from_side: str, to_side: str
129
+ ) -> Optional[T]:
130
+ """Move one element between list ends atomically.
131
+
132
+ Redis executes the command before its result is decoded. A decoding
133
+ error does not undo the command's effects.
134
+
135
+ Args:
136
+ key: The database key, without an Encore key prefix.
137
+ destination: The destination key, without an Encore key prefix.
138
+ from_side: The source end: LEFT or RIGHT, case-insensitively.
139
+ to_side: The destination end: LEFT or RIGHT, case-insensitively.
140
+
141
+ Returns:
142
+ The decoded moved element, or None if the source is empty or
143
+ missing.
144
+
145
+ Raises:
146
+ UnicodeDecodeError: A value is not valid UTF-8 when the type
147
+ argument is str.
148
+ ValueError: A stored value cannot be parsed as int or float.
149
+ EncoreError: Redis rejects the command or the request fails.
150
+ """
151
+ result = await self._get_handle().list_lmove(
152
+ key, destination, from_side, to_side, source=active_ctx_bytes()
153
+ )
154
+ return decode_optional(result, self._value_type)
155
+
156
+
157
+ class _LpopCommand(TypedCommand[T]):
158
+ """A callable LPOP command with selectable value decoding."""
159
+
160
+ def __getitem__(self, value_type: type[U]) -> _LpopCommand[U]:
161
+ """Select the value type for this command.
162
+
163
+ Use lpop[T](...) to decode stored values as T. Selecting a type does not
164
+ open a connection or change the decoder of an existing command.
165
+
166
+ Args:
167
+ value_type: bytes, str, int, float, or a class implementing
168
+ RedisValue.
169
+
170
+ Returns:
171
+ An independent command with the same arguments and the selected
172
+ decoder. Keys and other command metadata retain their existing
173
+ types.
174
+ """
175
+ return _LpopCommand(self._get_handle, value_type)
176
+
177
+ async def __call__(
178
+ self, key: str, *, count: int | None = None
179
+ ) -> T | list[T] | None:
180
+ """Remove elements from the head of a list.
181
+
182
+ Redis executes the command before its result is decoded. A decoding
183
+ error does not undo the command's effects.
184
+
185
+ Args:
186
+ key: The database key, without an Encore key prefix.
187
+ count: The nonnegative maximum number of elements to remove. None
188
+ removes and returns a single decoded element instead of a list.
189
+
190
+ Returns:
191
+ Without count, a single decoded element. With count, a list of up to
192
+ count elements. Returns None if the key is missing.
193
+
194
+ Raises:
195
+ UnicodeDecodeError: A value is not valid UTF-8 when the type
196
+ argument is str.
197
+ ValueError: A stored value cannot be parsed as int or float.
198
+ EncoreError: Redis rejects the command or the request fails.
199
+ """
200
+ result = await self._get_handle().list_lpop(
201
+ key, count=count, source=active_ctx_bytes()
202
+ )
203
+ return decode_pop(result, self._value_type)
204
+
205
+
206
+ class _RpopCommand(TypedCommand[T]):
207
+ """A callable RPOP command with selectable value decoding."""
208
+
209
+ def __getitem__(self, value_type: type[U]) -> _RpopCommand[U]:
210
+ """Select the value type for this command.
211
+
212
+ Use rpop[T](...) to decode stored values as T. Selecting a type does not
213
+ open a connection or change the decoder of an existing command.
214
+
215
+ Args:
216
+ value_type: bytes, str, int, float, or a class implementing
217
+ RedisValue.
218
+
219
+ Returns:
220
+ An independent command with the same arguments and the selected
221
+ decoder. Keys and other command metadata retain their existing
222
+ types.
223
+ """
224
+ return _RpopCommand(self._get_handle, value_type)
225
+
226
+ async def __call__(
227
+ self, key: str, *, count: int | None = None
228
+ ) -> T | list[T] | None:
229
+ """Remove elements from the tail of a list.
230
+
231
+ Redis executes the command before its result is decoded. A decoding
232
+ error does not undo the command's effects.
233
+
234
+ Args:
235
+ key: The database key, without an Encore key prefix.
236
+ count: The nonnegative maximum number of elements to remove. None
237
+ removes and returns a single decoded element instead of a list.
238
+
239
+ Returns:
240
+ Without count, a single decoded element. With count, a list in
241
+ removal order of up to count elements. Returns None if the key is
242
+ missing.
243
+
244
+ Raises:
245
+ UnicodeDecodeError: A value is not valid UTF-8 when the type
246
+ argument is str.
247
+ ValueError: A stored value cannot be parsed as int or float.
248
+ EncoreError: Redis rejects the command or the request fails.
249
+ """
250
+ result = await self._get_handle().list_rpop(
251
+ key, count=count, source=active_ctx_bytes()
252
+ )
253
+ return decode_pop(result, self._value_type)
254
+
255
+
256
+ class ReadOnlyInterface(CommandInterface):
257
+ """Commands available through a read-only database handle."""
258
+
259
+ @property
260
+ def lindex(self) -> _LindexCommand[bytes]:
261
+ """The callable LINDEX command.
262
+
263
+ Use lindex[T](...) to select the decoded value type. Plain calls keep
264
+ stored values as bytes; keys and command metadata are unchanged.
265
+ """
266
+ return _LindexCommand(self._get_handle, bytes)
267
+
268
+ async def llen(self, key: str) -> int:
269
+ """Return the number of elements in a list.
270
+
271
+ Args:
272
+ key: The database key, without an Encore key prefix.
273
+
274
+ Returns:
275
+ The list length, or zero if the key does not exist.
276
+
277
+ Raises:
278
+ EncoreError: Redis rejects the command or the request fails.
279
+ """
280
+ return await self._get_handle().list_llen(key, source=active_ctx_bytes())
281
+
282
+ async def lpos(
283
+ self,
284
+ key: str,
285
+ element: Value,
286
+ *,
287
+ rank: int | None = None,
288
+ count: int | None = None,
289
+ maxlen: int | None = None,
290
+ ) -> int | list[int] | None:
291
+ """Find the positions of matching elements in a list.
292
+
293
+ Args:
294
+ key: The database key, without an Encore key prefix.
295
+ element: The element to encode and find.
296
+ rank: Which match to start with, starting at one. Negative ranks
297
+ search from the tail; zero is invalid.
298
+ count: The maximum number of positions to return; zero returns all
299
+ matches. None returns a single position.
300
+ maxlen: The maximum number of elements to inspect; zero means
301
+ unlimited.
302
+
303
+ Returns:
304
+ Without count, the matching index or None. With count, a list of
305
+ indices, empty if nothing matches.
306
+
307
+ Raises:
308
+ EncoreError: Redis rejects the command or the request fails.
309
+ """
310
+ return await self._get_handle().list_lpos(
311
+ key,
312
+ encode(element),
313
+ rank=rank,
314
+ count=count,
315
+ maxlen=maxlen,
316
+ source=active_ctx_bytes(),
317
+ )
318
+
319
+ @property
320
+ def lrange(self) -> _LrangeCommand[bytes]:
321
+ """The callable LRANGE command.
322
+
323
+ Use lrange[T](...) to select the decoded value type. Plain calls keep
324
+ stored values as bytes; keys and command metadata are unchanged.
325
+ """
326
+ return _LrangeCommand(self._get_handle, bytes)
327
+
328
+
329
+ class Interface(ReadOnlyInterface):
330
+ """Read and write commands."""
331
+
332
+ async def linsert(self, key: str, position: str, pivot: Value, value: Value) -> int:
333
+ """Insert an element before or after the first matching pivot.
334
+
335
+ Args:
336
+ key: The database key, without an Encore key prefix.
337
+ position: BEFORE or AFTER, case-insensitively, relative to the first
338
+ pivot.
339
+ pivot: The existing element to encode and insert beside.
340
+ value: The value to encode and store.
341
+
342
+ Returns:
343
+ The resulting length, zero if the key is missing, or -1 if the pivot
344
+ is missing.
345
+
346
+ Raises:
347
+ EncoreError: Redis rejects the command or the request fails.
348
+ """
349
+ return await self._get_handle().list_linsert(
350
+ key, position, encode(pivot), encode(value), source=active_ctx_bytes()
351
+ )
352
+
353
+ @property
354
+ def lmove(self) -> _LmoveCommand[bytes]:
355
+ """The callable LMOVE command.
356
+
357
+ Use lmove[T](...) to select the decoded value type. Plain calls keep
358
+ stored values as bytes; keys and command metadata are unchanged.
359
+ """
360
+ return _LmoveCommand(self._get_handle, bytes)
361
+
362
+ @property
363
+ def lpop(self) -> _LpopCommand[bytes]:
364
+ """The callable LPOP command.
365
+
366
+ Use lpop[T](...) to select the decoded value type. Plain calls keep
367
+ stored values as bytes; keys and command metadata are unchanged.
368
+ """
369
+ return _LpopCommand(self._get_handle, bytes)
370
+
371
+ async def lpush(self, key: str, value: Value, *values: Value) -> int:
372
+ """Push values onto the head of a list, creating it if needed.
373
+
374
+ Args:
375
+ key: The database key, without an Encore key prefix.
376
+ value: The first value to encode and push.
377
+ *values: Additional values to encode, in order.
378
+
379
+ Returns:
380
+ The resulting list length. Values are pushed in input order, so the
381
+ last supplied value becomes the head.
382
+
383
+ Raises:
384
+ EncoreError: Redis rejects the command or the request fails.
385
+ """
386
+ return await self._get_handle().list_lpush(
387
+ key,
388
+ [encode(value), *(encode(item) for item in values)],
389
+ source=active_ctx_bytes(),
390
+ )
391
+
392
+ async def lpushx(self, key: str, value: Value, *values: Value) -> int:
393
+ """Push values onto the head of an existing list.
394
+
395
+ Args:
396
+ key: The database key, without an Encore key prefix.
397
+ value: The first value to encode and push.
398
+ *values: Additional values to encode, in order.
399
+
400
+ Returns:
401
+ The resulting length, or zero if the key is missing. The last
402
+ supplied value becomes the head.
403
+
404
+ Raises:
405
+ EncoreError: Redis rejects the command or the request fails.
406
+ """
407
+ values = (value, *values)
408
+ return await self._get_handle().list_lpushx(
409
+ key, [encode(value) for value in values], source=active_ctx_bytes()
410
+ )
411
+
412
+ async def lrem(self, key: str, count: int, value: Value) -> int:
413
+ """Remove matching values from a list.
414
+
415
+ Args:
416
+ key: The database key, without an Encore key prefix.
417
+ count: Remove up to count matches from the head if positive,
418
+ abs(count) from the tail if negative, or all matches if zero.
419
+ value: The value to encode and remove.
420
+
421
+ Returns:
422
+ The number of elements removed.
423
+
424
+ Raises:
425
+ EncoreError: Redis rejects the command or the request fails.
426
+ """
427
+ return await self._get_handle().list_lrem(
428
+ key, count, encode(value), source=active_ctx_bytes()
429
+ )
430
+
431
+ async def lset(self, key: str, index: int, value: Value) -> None:
432
+ """Replace the element at a list index.
433
+
434
+ Args:
435
+ key: The database key, without an Encore key prefix.
436
+ index: The zero-based index; negative values count from the end.
437
+ value: The value to encode and store.
438
+
439
+ Raises:
440
+ EncoreError: The key is missing, the index is out of range, or Redis
441
+ rejects the command or the request fails.
442
+ """
443
+ return await self._get_handle().list_lset(
444
+ key, index, encode(value), source=active_ctx_bytes()
445
+ )
446
+
447
+ async def ltrim(self, key: str, start: int, stop: int) -> None:
448
+ """Keep only an inclusive range of list elements.
449
+
450
+ Args:
451
+ key: The database key, without an Encore key prefix.
452
+ start: The inclusive starting index; negative values count from the
453
+ end.
454
+ stop: The inclusive ending index; negative values count from the
455
+ end.
456
+
457
+ Raises:
458
+ EncoreError: Redis rejects the command or the request fails.
459
+ """
460
+ return await self._get_handle().list_ltrim(
461
+ key, start, stop, source=active_ctx_bytes()
462
+ )
463
+
464
+ @property
465
+ def rpop(self) -> _RpopCommand[bytes]:
466
+ """The callable RPOP command.
467
+
468
+ Use rpop[T](...) to select the decoded value type. Plain calls keep
469
+ stored values as bytes; keys and command metadata are unchanged.
470
+ """
471
+ return _RpopCommand(self._get_handle, bytes)
472
+
473
+ async def rpush(self, key: str, value: Value, *values: Value) -> int:
474
+ """Push values onto the tail of a list, creating it if needed.
475
+
476
+ Args:
477
+ key: The database key, without an Encore key prefix.
478
+ value: The first value to encode and push.
479
+ *values: Additional values to encode, in order.
480
+
481
+ Returns:
482
+ The resulting list length. Values retain their input order.
483
+
484
+ Raises:
485
+ EncoreError: Redis rejects the command or the request fails.
486
+ """
487
+ return await self._get_handle().list_rpush(
488
+ key,
489
+ [encode(value), *(encode(item) for item in values)],
490
+ source=active_ctx_bytes(),
491
+ )
492
+
493
+ async def rpushx(self, key: str, value: Value, *values: Value) -> int:
494
+ """Push values onto the tail of an existing list.
495
+
496
+ Args:
497
+ key: The database key, without an Encore key prefix.
498
+ value: The first value to encode and push.
499
+ *values: Additional values to encode, in order.
500
+
501
+ Returns:
502
+ The resulting length, or zero if the key is missing. Values retain
503
+ their input order.
504
+
505
+ Raises:
506
+ EncoreError: Redis rejects the command or the request fails.
507
+ """
508
+ values = (value, *values)
509
+ return await self._get_handle().list_rpushx(
510
+ key, [encode(value) for value in values], source=active_ctx_bytes()
511
+ )