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,614 @@
1
+ """RedisJSON commands using Python JSON values.
2
+
3
+ Values are serialized as JSON, including strings. Document replies are decoded
4
+ into Python values; JSONPath queries preserve the server's arrays of matches.
5
+ Requires a server with RedisJSON support.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json as _json
11
+ from typing import Any
12
+
13
+ from ...tracing._context import active_ctx_bytes
14
+ from ._base import CommandInterface
15
+
16
+
17
+ def _encode(value: Any) -> str:
18
+ """Serialize a Python value as compact JSON text.
19
+
20
+ Args:
21
+ value: A JSON-serializable value with finite numbers and no circular
22
+ references.
23
+
24
+ Returns:
25
+ JSON text with non-ASCII characters preserved.
26
+ """
27
+ return _json.dumps(
28
+ value, ensure_ascii=False, allow_nan=False, separators=(",", ":")
29
+ )
30
+
31
+
32
+ def _decode(value: Any) -> Any:
33
+ """Decode JSON byte strings within a RedisJSON reply.
34
+
35
+ Args:
36
+ value: A byte string, a list of replies, or a scalar to preserve.
37
+
38
+ Returns:
39
+ Decoded Python JSON values. Lists are traversed recursively; other
40
+ values are unchanged.
41
+
42
+ Raises:
43
+ UnicodeDecodeError: JSON bytes use an invalid text encoding.
44
+ ValueError: A byte string is not valid JSON.
45
+ """
46
+ if isinstance(value, bytes):
47
+ return _json.loads(value)
48
+ if isinstance(value, list):
49
+ return [_decode(item) for item in value]
50
+ return value
51
+
52
+
53
+ def _text(value: Any) -> Any:
54
+ """Decode text byte strings within a RedisJSON metadata reply.
55
+
56
+ Args:
57
+ value: A byte string, a list of replies, or a scalar to preserve.
58
+
59
+ Returns:
60
+ UTF-8-decoded strings. Lists are traversed recursively; other values are
61
+ unchanged.
62
+
63
+ Raises:
64
+ UnicodeDecodeError: A byte string is not valid UTF-8.
65
+ """
66
+ if isinstance(value, bytes):
67
+ return value.decode("utf-8")
68
+ if isinstance(value, list):
69
+ return [_text(item) for item in value]
70
+ return value
71
+
72
+
73
+ class ReadOnlyInterface(CommandInterface):
74
+ """Commands available through a read-only database handle."""
75
+
76
+ async def arrindex(
77
+ self,
78
+ key: str,
79
+ path: str,
80
+ value: Any,
81
+ *,
82
+ start: int | None = None,
83
+ stop: int | None = None,
84
+ ) -> Any:
85
+ """Find a JSON value within arrays selected by a path.
86
+
87
+ Args:
88
+ key: The database key, without an Encore key prefix.
89
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
90
+ expressions start with "$" and can select multiple values.
91
+ value: A Python JSON-serializable value; strings are encoded as JSON
92
+ strings, not treated as pre-encoded JSON. Numbers must be
93
+ finite, and values must not contain circular references.
94
+ start: The inclusive start index; negative indices count from the
95
+ end. Defaults to zero.
96
+ stop: The exclusive stop index; zero means through the end. Negative
97
+ indices count from the end. Requires start.
98
+
99
+ Returns:
100
+ For JSONPath, one index per match, -1 if not found, or None for a
101
+ non-array match. Legacy paths return a scalar index.
102
+
103
+ Raises:
104
+ EncoreError: Redis rejects the command or the request fails.
105
+ """
106
+ return await self._get_handle().json_arrindex(
107
+ key, path, _encode(value), start=start, stop=stop, source=active_ctx_bytes()
108
+ )
109
+
110
+ async def arrlen(self, key: str, *, path: str = "$") -> Any:
111
+ """Return the lengths of arrays selected by a path.
112
+
113
+ Args:
114
+ key: The database key, without an Encore key prefix.
115
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
116
+ expressions start with "$" and can select multiple values.
117
+
118
+ Returns:
119
+ For JSONPath, one length per match or None for a non-array match.
120
+ Legacy paths return a scalar length.
121
+
122
+ Raises:
123
+ EncoreError: Redis rejects the command or the request fails.
124
+ """
125
+ return await self._get_handle().json_arrlen(
126
+ key, path=path, source=active_ctx_bytes()
127
+ )
128
+
129
+ async def get(
130
+ self,
131
+ key: str,
132
+ *paths: str,
133
+ indent: str | None = None,
134
+ newline: str | None = None,
135
+ space: str | None = None,
136
+ ) -> Any:
137
+ """Return decoded JSON values selected by one or more paths.
138
+
139
+ Args:
140
+ key: The database key, without an Encore key prefix.
141
+ *paths: Paths to retrieve; omit for the root document.
142
+ indent: The indentation in the server's JSON text; formatting is
143
+ discarded when decoded into Python values.
144
+ newline: The newline text in the server response; formatting is
145
+ discarded when decoded into Python values.
146
+ space: The spacing in the server response; formatting is discarded
147
+ when decoded into Python values.
148
+
149
+ Returns:
150
+ Python JSON values, or None if the key is missing. A single JSONPath
151
+ returns a list of matches; multiple paths return a dictionary keyed
152
+ by path. With no paths, returns the root document.
153
+
154
+ Raises:
155
+ UnicodeDecodeError: The server response uses an invalid text
156
+ encoding.
157
+ ValueError: The server response is not valid JSON.
158
+ EncoreError: Redis rejects the command or the request fails.
159
+ """
160
+ return _decode(
161
+ await self._get_handle().json_get(
162
+ key,
163
+ paths=paths or None,
164
+ indent=indent,
165
+ newline=newline,
166
+ space=space,
167
+ source=active_ctx_bytes(),
168
+ )
169
+ )
170
+
171
+ async def mget(self, key: str, *keys: str, path: str) -> Any:
172
+ """Return decoded JSON values from several keys in input order.
173
+
174
+ Args:
175
+ key: The first database key, without an Encore prefix.
176
+ *keys: Additional database keys, without Encore prefixes.
177
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
178
+ expressions start with "$" and can select multiple values.
179
+
180
+ Returns:
181
+ One result per key, with None for missing keys or paths. JSONPath
182
+ results retain their lists of matches.
183
+
184
+ Raises:
185
+ UnicodeDecodeError: The server response uses an invalid text
186
+ encoding.
187
+ ValueError: The server response is not valid JSON.
188
+ EncoreError: Redis rejects the command or the request fails.
189
+ """
190
+ keys = (key, *keys)
191
+ return _decode(
192
+ await self._get_handle().json_mget(keys, path, source=active_ctx_bytes())
193
+ )
194
+
195
+ async def objkeys(self, key: str, *, path: str = "$") -> Any:
196
+ """Return field names of JSON objects selected by a path.
197
+
198
+ Args:
199
+ key: The database key, without an Encore key prefix.
200
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
201
+ expressions start with "$" and can select multiple values.
202
+
203
+ Returns:
204
+ For JSONPath, one list of Python string field names per match or
205
+ None for a non-object match. Legacy paths return a single list of
206
+ names.
207
+
208
+ Raises:
209
+ UnicodeDecodeError: The server response uses an invalid text
210
+ encoding.
211
+ EncoreError: Redis rejects the command or the request fails.
212
+ """
213
+ return _text(
214
+ await self._get_handle().json_objkeys(
215
+ key, path=path, source=active_ctx_bytes()
216
+ )
217
+ )
218
+
219
+ async def objlen(self, key: str, *, path: str = "$") -> Any:
220
+ """Return the sizes of JSON objects selected by a path.
221
+
222
+ Args:
223
+ key: The database key, without an Encore key prefix.
224
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
225
+ expressions start with "$" and can select multiple values.
226
+
227
+ Returns:
228
+ For JSONPath, one field count per match or None for a non-object
229
+ match. Legacy paths return a scalar count.
230
+
231
+ Raises:
232
+ EncoreError: Redis rejects the command or the request fails.
233
+ """
234
+ return await self._get_handle().json_objlen(
235
+ key, path=path, source=active_ctx_bytes()
236
+ )
237
+
238
+ async def strlen(self, key: str, *, path: str = "$") -> Any:
239
+ """Return the lengths of JSON strings selected by a path.
240
+
241
+ Args:
242
+ key: The database key, without an Encore key prefix.
243
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
244
+ expressions start with "$" and can select multiple values.
245
+
246
+ Returns:
247
+ For JSONPath, one length per match or None for a non-string match.
248
+ Legacy paths return a scalar length.
249
+
250
+ Raises:
251
+ EncoreError: Redis rejects the command or the request fails.
252
+ """
253
+ return await self._get_handle().json_strlen(
254
+ key, path=path, source=active_ctx_bytes()
255
+ )
256
+
257
+ async def type(self, key: str, *, path: str = "$") -> Any:
258
+ """Return the JSON types of values selected by a path.
259
+
260
+ Args:
261
+ key: The database key, without an Encore key prefix.
262
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
263
+ expressions start with "$" and can select multiple values.
264
+
265
+ Returns:
266
+ For JSONPath, a list of Python string type names. Legacy paths
267
+ return a single type name, or None if the path is missing.
268
+
269
+ Raises:
270
+ UnicodeDecodeError: The server response uses an invalid text
271
+ encoding.
272
+ EncoreError: Redis rejects the command or the request fails.
273
+ """
274
+ return _text(
275
+ await self._get_handle().json_type(
276
+ key, path=path, source=active_ctx_bytes()
277
+ )
278
+ )
279
+
280
+
281
+ class Interface(ReadOnlyInterface):
282
+ """Read and write commands."""
283
+
284
+ async def arrappend(self, key: str, path: str, value: Any, *values: Any) -> Any:
285
+ """Append Python JSON values to arrays selected by a path.
286
+
287
+ Args:
288
+ key: The database key, without an Encore key prefix.
289
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
290
+ expressions start with "$" and can select multiple values.
291
+ value: The first JSON value to append.
292
+ Numbers must be finite, and values must not contain circular
293
+ references.
294
+ *values: Additional JSON values with the same restrictions,
295
+ in order.
296
+
297
+ Returns:
298
+ For JSONPath, one resulting length per match or None for a non-array
299
+ match. Legacy paths return a scalar length.
300
+
301
+ Raises:
302
+ EncoreError: Redis rejects the command or the request fails.
303
+ """
304
+ values = (value, *values)
305
+ return await self._get_handle().json_arrappend(
306
+ key, path, [_encode(value) for value in values], source=active_ctx_bytes()
307
+ )
308
+
309
+ async def arrinsert(
310
+ self, key: str, path: str, index: int, value: Any, *values: Any
311
+ ) -> Any:
312
+ """Insert Python JSON values into arrays selected by a path.
313
+
314
+ Args:
315
+ key: The database key, without an Encore key prefix.
316
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
317
+ expressions start with "$" and can select multiple values.
318
+ index: The zero-based index; negative values count from the end.
319
+ value: The first JSON value to insert.
320
+ Numbers must be finite, and values must not contain circular
321
+ references.
322
+ *values: Additional JSON values with the same restrictions,
323
+ in order.
324
+
325
+ Returns:
326
+ For JSONPath, one resulting length per match or None for a non-array
327
+ match. Legacy paths return a scalar length.
328
+
329
+ Raises:
330
+ EncoreError: Redis rejects the command or the request fails.
331
+ """
332
+ values = (value, *values)
333
+ return await self._get_handle().json_arrinsert(
334
+ key,
335
+ path,
336
+ index,
337
+ [_encode(value) for value in values],
338
+ source=active_ctx_bytes(),
339
+ )
340
+
341
+ async def arrpop(self, key: str, *, path: str = "$", index: int = -1) -> Any:
342
+ """Remove and return elements from arrays selected by a path.
343
+
344
+ The command executes before the reply is decoded. A decoding error does
345
+ not undo changes to the stored document.
346
+
347
+ Args:
348
+ key: The database key, without an Encore key prefix.
349
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
350
+ expressions start with "$" and can select multiple values.
351
+ index: The index to remove; -1 selects the last element.
352
+ Out-of-range indices are clamped to the nearest end.
353
+
354
+ Returns:
355
+ For JSONPath, one decoded Python value per match, or None for an
356
+ empty array or non-array match. Legacy paths return a single decoded
357
+ value.
358
+
359
+ Raises:
360
+ UnicodeDecodeError: The server response uses an invalid text
361
+ encoding.
362
+ ValueError: The server response is not valid JSON.
363
+ EncoreError: Redis rejects the command or the request fails.
364
+ """
365
+ return _decode(
366
+ await self._get_handle().json_arrpop(
367
+ key, path=path, index=index, source=active_ctx_bytes()
368
+ )
369
+ )
370
+
371
+ async def arrtrim(self, key: str, path: str, start: int, stop: int) -> Any:
372
+ """Keep an inclusive range of elements in selected JSON arrays.
373
+
374
+ Args:
375
+ key: The database key, without an Encore key prefix.
376
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
377
+ expressions start with "$" and can select multiple values.
378
+ start: The inclusive starting index; negative values count from the
379
+ end.
380
+ stop: The inclusive ending index; negative values count from the
381
+ end.
382
+
383
+ Returns:
384
+ For JSONPath, one resulting length per match or None for a non-array
385
+ match. Legacy paths return a scalar length.
386
+
387
+ Raises:
388
+ EncoreError: Redis rejects the command or the request fails.
389
+ """
390
+ return await self._get_handle().json_arrtrim(
391
+ key, path, start, stop, source=active_ctx_bytes()
392
+ )
393
+
394
+ async def clear(self, key: str, *, path: str = "$") -> Any:
395
+ """Empty selected containers and reset selected numbers to zero.
396
+
397
+ Args:
398
+ key: The database key, without an Encore key prefix.
399
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
400
+ expressions start with "$" and can select multiple values.
401
+
402
+ Returns:
403
+ The number of values changed; values already empty or zero are not
404
+ counted.
405
+
406
+ Raises:
407
+ EncoreError: Redis rejects the command or the request fails.
408
+ """
409
+ return await self._get_handle().json_clear(
410
+ key, path=path, source=active_ctx_bytes()
411
+ )
412
+
413
+ async def delete(self, key: str, *, path: str = "$") -> Any:
414
+ """Delete the JSON values selected by a path.
415
+
416
+ Args:
417
+ key: The database key, without an Encore key prefix.
418
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
419
+ expressions start with "$" and can select multiple values.
420
+
421
+ Returns:
422
+ The number of values deleted, or zero if nothing matches.
423
+
424
+ Raises:
425
+ EncoreError: Redis rejects the command or the request fails.
426
+ """
427
+ return await self._get_handle().json_delete(
428
+ key, path=path, source=active_ctx_bytes()
429
+ )
430
+
431
+ async def forget(self, key: str, *, path: str = "$") -> Any:
432
+ """Delete selected JSON values, as an alias for delete.
433
+
434
+ Args:
435
+ key: The database key, without an Encore key prefix.
436
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
437
+ expressions start with "$" and can select multiple values.
438
+
439
+ Returns:
440
+ The number of values deleted, or zero if nothing matches.
441
+
442
+ Raises:
443
+ EncoreError: Redis rejects the command or the request fails.
444
+ """
445
+ return await self._get_handle().json_forget(
446
+ key, path=path, source=active_ctx_bytes()
447
+ )
448
+
449
+ async def merge(self, key: str, path: str, value: Any) -> Any:
450
+ """Apply a JSON Merge Patch to the values selected by a path.
451
+
452
+ Uses JSON Merge Patch semantics: object fields are merged, null fields
453
+ remove existing fields, and arrays or scalars replace the target value.
454
+
455
+ Args:
456
+ key: The database key, without an Encore key prefix.
457
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
458
+ expressions start with "$" and can select multiple values.
459
+ value: A Python JSON-serializable value; strings are encoded as JSON
460
+ strings, not treated as pre-encoded JSON. Numbers must be
461
+ finite, and values must not contain circular references.
462
+
463
+ Returns:
464
+ b"OK" when the merge succeeds.
465
+
466
+ Raises:
467
+ EncoreError: Redis rejects the command or the request fails.
468
+ """
469
+ return await self._get_handle().json_merge(
470
+ key, path, _encode(value), source=active_ctx_bytes()
471
+ )
472
+
473
+ async def mset(
474
+ self, item: tuple[str, str, Any], *items: tuple[str, str, Any]
475
+ ) -> Any:
476
+ """Set multiple JSON values atomically.
477
+
478
+ Args:
479
+ item: The first (key, path, Python JSON value) tuple. Numbers must
480
+ be finite, and values must not contain circular references.
481
+ *items: Additional tuples of the same shape, in order.
482
+
483
+ Raises:
484
+ EncoreError: Redis rejects the command or the request fails.
485
+ """
486
+ items = (item, *items)
487
+ return await self._get_handle().json_mset(
488
+ [(key, path, _encode(value)) for key, path, value in items],
489
+ source=active_ctx_bytes(),
490
+ )
491
+
492
+ async def numincrby(self, key: str, path: str, number: float) -> Any:
493
+ """Add a number to JSON numeric values selected by a path.
494
+
495
+ The command executes before the reply is decoded. A decoding error does
496
+ not undo changes to the stored document.
497
+
498
+ Args:
499
+ key: The database key, without an Encore key prefix.
500
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
501
+ expressions start with "$" and can select multiple values.
502
+ number: The number used in the arithmetic operation.
503
+
504
+ Returns:
505
+ For JSONPath, a list of resulting numbers or None for non-numeric
506
+ matches. Legacy paths return a scalar number.
507
+
508
+ Raises:
509
+ UnicodeDecodeError: The server response uses an invalid text
510
+ encoding.
511
+ ValueError: The server response is not valid JSON.
512
+ EncoreError: Redis rejects the command or the request fails.
513
+ """
514
+ return _decode(
515
+ await self._get_handle().json_numincrby(
516
+ key, path, number, source=active_ctx_bytes()
517
+ )
518
+ )
519
+
520
+ async def nummultby(self, key: str, path: str, number: float) -> Any:
521
+ """Multiply JSON numeric values selected by a path.
522
+
523
+ The command executes before the reply is decoded. A decoding error does
524
+ not undo changes to the stored document.
525
+
526
+ Args:
527
+ key: The database key, without an Encore key prefix.
528
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
529
+ expressions start with "$" and can select multiple values.
530
+ number: The number used in the arithmetic operation.
531
+
532
+ Returns:
533
+ For JSONPath, a list of resulting numbers or None for non-numeric
534
+ matches. Legacy paths return a scalar number.
535
+
536
+ Raises:
537
+ UnicodeDecodeError: The server response uses an invalid text
538
+ encoding.
539
+ ValueError: The server response is not valid JSON.
540
+ EncoreError: Redis rejects the command or the request fails.
541
+ """
542
+ return _decode(
543
+ await self._get_handle().json_nummultby(
544
+ key, path, number, source=active_ctx_bytes()
545
+ )
546
+ )
547
+
548
+ async def set(
549
+ self, key: str, path: str, value: Any, *, condition: str | None = None
550
+ ) -> Any:
551
+ """Set a JSON value, optionally requiring an existing or new path.
552
+
553
+ Args:
554
+ key: The database key, without an Encore key prefix.
555
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
556
+ expressions start with "$" and can select multiple values.
557
+ value: A Python JSON-serializable value; strings are encoded as JSON
558
+ strings, not treated as pre-encoded JSON. Numbers must be
559
+ finite, and values must not contain circular references.
560
+ condition: NX to set only a new path, XX to set only an existing
561
+ path, or None for no condition. Case-insensitive.
562
+
563
+ Returns:
564
+ b"OK" if the value was set, or None if the condition failed or the
565
+ server could not create the path.
566
+
567
+ Raises:
568
+ EncoreError: Redis rejects the command or the request fails.
569
+ """
570
+ return await self._get_handle().json_set(
571
+ key, path, _encode(value), condition=condition, source=active_ctx_bytes()
572
+ )
573
+
574
+ async def strappend(self, key: str, path: str, value: Any) -> Any:
575
+ """Append a Python string to JSON strings selected by a path.
576
+
577
+ Args:
578
+ key: The database key, without an Encore key prefix.
579
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
580
+ expressions start with "$" and can select multiple values.
581
+ value: The Python string to append; it is JSON-encoded
582
+ automatically. Numbers must be finite, and values must not
583
+ contain circular references.
584
+
585
+ Returns:
586
+ For JSONPath, one resulting length per match or None for a
587
+ non-string match. Legacy paths return a scalar length.
588
+
589
+ Raises:
590
+ EncoreError: Redis rejects the command or the request fails.
591
+ """
592
+ return await self._get_handle().json_strappend(
593
+ key, path, _encode(value), source=active_ctx_bytes()
594
+ )
595
+
596
+ async def toggle(self, key: str, *, path: str = "$") -> Any:
597
+ """Invert JSON boolean values selected by a path.
598
+
599
+ Args:
600
+ key: The database key, without an Encore key prefix.
601
+ path: The JSONPath expression, or a legacy RedisJSON path. JSONPath
602
+ expressions start with "$" and can select multiple values.
603
+
604
+ Returns:
605
+ For JSONPath, a list of 0/1 results or None for non-boolean matches.
606
+ Legacy paths return a scalar 0 or 1, or None for a non-boolean
607
+ match.
608
+
609
+ Raises:
610
+ EncoreError: Redis rejects the command or the request fails.
611
+ """
612
+ return await self._get_handle().json_toggle(
613
+ key, path=path, source=active_ctx_bytes()
614
+ )