redis 5.3.0b5__py3-none-any.whl → 6.0.0__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 (50) hide show
  1. redis/__init__.py +2 -11
  2. redis/_parsers/base.py +14 -2
  3. redis/_parsers/resp3.py +2 -2
  4. redis/asyncio/client.py +102 -82
  5. redis/asyncio/cluster.py +147 -102
  6. redis/asyncio/connection.py +77 -24
  7. redis/asyncio/lock.py +26 -5
  8. redis/asyncio/retry.py +12 -0
  9. redis/asyncio/sentinel.py +11 -1
  10. redis/asyncio/utils.py +1 -1
  11. redis/auth/token.py +6 -2
  12. redis/backoff.py +15 -0
  13. redis/client.py +106 -98
  14. redis/cluster.py +208 -79
  15. redis/commands/cluster.py +1 -11
  16. redis/commands/core.py +219 -207
  17. redis/commands/helpers.py +19 -76
  18. redis/commands/json/__init__.py +1 -1
  19. redis/commands/redismodules.py +5 -17
  20. redis/commands/search/aggregation.py +3 -1
  21. redis/commands/search/commands.py +43 -16
  22. redis/commands/search/dialect.py +3 -0
  23. redis/commands/search/profile_information.py +14 -0
  24. redis/commands/search/query.py +5 -1
  25. redis/commands/timeseries/__init__.py +1 -1
  26. redis/commands/vectorset/__init__.py +46 -0
  27. redis/commands/vectorset/commands.py +367 -0
  28. redis/commands/vectorset/utils.py +94 -0
  29. redis/connection.py +78 -29
  30. redis/exceptions.py +4 -1
  31. redis/lock.py +24 -4
  32. redis/ocsp.py +2 -1
  33. redis/retry.py +12 -0
  34. redis/sentinel.py +3 -1
  35. redis/utils.py +114 -1
  36. {redis-5.3.0b5.dist-info → redis-6.0.0.dist-info}/METADATA +57 -23
  37. redis-6.0.0.dist-info/RECORD +78 -0
  38. {redis-5.3.0b5.dist-info → redis-6.0.0.dist-info}/WHEEL +1 -2
  39. redis/commands/graph/__init__.py +0 -263
  40. redis/commands/graph/commands.py +0 -313
  41. redis/commands/graph/edge.py +0 -91
  42. redis/commands/graph/exceptions.py +0 -3
  43. redis/commands/graph/execution_plan.py +0 -211
  44. redis/commands/graph/node.py +0 -88
  45. redis/commands/graph/path.py +0 -78
  46. redis/commands/graph/query_result.py +0 -588
  47. redis-5.3.0b5.dist-info/RECORD +0 -82
  48. redis-5.3.0b5.dist-info/top_level.txt +0 -1
  49. /redis/commands/search/{indexDefinition.py → index_definition.py} +0 -0
  50. {redis-5.3.0b5.dist-info → redis-6.0.0.dist-info/licenses}/LICENSE +0 -0
redis/client.py CHANGED
@@ -2,7 +2,6 @@ import copy
2
2
  import re
3
3
  import threading
4
4
  import time
5
- import warnings
6
5
  from itertools import chain
7
6
  from typing import (
8
7
  TYPE_CHECKING,
@@ -12,6 +11,7 @@ from typing import (
12
11
  List,
13
12
  Mapping,
14
13
  Optional,
14
+ Set,
15
15
  Type,
16
16
  Union,
17
17
  )
@@ -23,6 +23,7 @@ from redis._parsers.helpers import (
23
23
  _RedisCallbacksRESP3,
24
24
  bool_ok,
25
25
  )
26
+ from redis.backoff import ExponentialWithJitterBackoff
26
27
  from redis.cache import CacheConfig, CacheInterface
27
28
  from redis.commands import (
28
29
  CoreCommands,
@@ -30,6 +31,7 @@ from redis.commands import (
30
31
  SentinelCommands,
31
32
  list_or_args,
32
33
  )
34
+ from redis.commands.core import Script
33
35
  from redis.connection import (
34
36
  AbstractConnection,
35
37
  ConnectionPool,
@@ -50,7 +52,6 @@ from redis.exceptions import (
50
52
  PubSubError,
51
53
  RedisError,
52
54
  ResponseError,
53
- TimeoutError,
54
55
  WatchError,
55
56
  )
56
57
  from redis.lock import Lock
@@ -58,9 +59,11 @@ from redis.retry import Retry
58
59
  from redis.utils import (
59
60
  HIREDIS_AVAILABLE,
60
61
  _set_info_logger,
62
+ deprecated_args,
61
63
  get_lib_version,
62
64
  safe_str,
63
65
  str_if_bytes,
66
+ truncate_text,
64
67
  )
65
68
 
66
69
  if TYPE_CHECKING:
@@ -188,6 +191,11 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
188
191
  client.auto_close_connection_pool = True
189
192
  return client
190
193
 
194
+ @deprecated_args(
195
+ args_to_warn=["retry_on_timeout"],
196
+ reason="TimeoutError is included by default.",
197
+ version="6.0.0",
198
+ )
191
199
  def __init__(
192
200
  self,
193
201
  host: str = "localhost",
@@ -202,19 +210,20 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
202
210
  unix_socket_path: Optional[str] = None,
203
211
  encoding: str = "utf-8",
204
212
  encoding_errors: str = "strict",
205
- charset: Optional[str] = None,
206
- errors: Optional[str] = None,
207
213
  decode_responses: bool = False,
208
214
  retry_on_timeout: bool = False,
215
+ retry: Retry = Retry(
216
+ backoff=ExponentialWithJitterBackoff(base=1, cap=10), retries=3
217
+ ),
209
218
  retry_on_error: Optional[List[Type[Exception]]] = None,
210
219
  ssl: bool = False,
211
220
  ssl_keyfile: Optional[str] = None,
212
221
  ssl_certfile: Optional[str] = None,
213
- ssl_cert_reqs: str = "required",
222
+ ssl_cert_reqs: Union[str, "ssl.VerifyMode"] = "required",
214
223
  ssl_ca_certs: Optional[str] = None,
215
224
  ssl_ca_path: Optional[str] = None,
216
225
  ssl_ca_data: Optional[str] = None,
217
- ssl_check_hostname: bool = False,
226
+ ssl_check_hostname: bool = True,
218
227
  ssl_password: Optional[str] = None,
219
228
  ssl_validate_ocsp: bool = False,
220
229
  ssl_validate_ocsp_stapled: bool = False,
@@ -229,7 +238,6 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
229
238
  lib_name: Optional[str] = "redis-py",
230
239
  lib_version: Optional[str] = get_lib_version(),
231
240
  username: Optional[str] = None,
232
- retry: Optional[Retry] = None,
233
241
  redis_connect_func: Optional[Callable[[], None]] = None,
234
242
  credential_provider: Optional[CredentialProvider] = None,
235
243
  protocol: Optional[int] = 2,
@@ -239,10 +247,24 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
239
247
  ) -> None:
240
248
  """
241
249
  Initialize a new Redis client.
242
- To specify a retry policy for specific errors, first set
243
- `retry_on_error` to a list of the error/s to retry on, then set
244
- `retry` to a valid `Retry` object.
245
- To retry on TimeoutError, `retry_on_timeout` can also be set to `True`.
250
+
251
+ To specify a retry policy for specific errors, you have two options:
252
+
253
+ 1. Set the `retry_on_error` to a list of the error/s to retry on, and
254
+ you can also set `retry` to a valid `Retry` object(in case the default
255
+ one is not appropriate) - with this approach the retries will be triggered
256
+ on the default errors specified in the Retry object enriched with the
257
+ errors specified in `retry_on_error`.
258
+
259
+ 2. Define a `Retry` object with configured 'supported_errors' and set
260
+ it to the `retry` parameter - with this approach you completely redefine
261
+ the errors on which retries will happen.
262
+
263
+ `retry_on_timeout` is deprecated - please include the TimeoutError
264
+ either in the Retry object or in the `retry_on_error` list.
265
+
266
+ When 'connection_pool' is provided - the retry configuration of the
267
+ provided pool will be used.
246
268
 
247
269
  Args:
248
270
 
@@ -255,24 +277,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
255
277
  else:
256
278
  self._event_dispatcher = event_dispatcher
257
279
  if not connection_pool:
258
- if charset is not None:
259
- warnings.warn(
260
- DeprecationWarning(
261
- '"charset" is deprecated. Use "encoding" instead'
262
- )
263
- )
264
- encoding = charset
265
- if errors is not None:
266
- warnings.warn(
267
- DeprecationWarning(
268
- '"errors" is deprecated. Use "encoding_errors" instead'
269
- )
270
- )
271
- encoding_errors = errors
272
280
  if not retry_on_error:
273
281
  retry_on_error = []
274
- if retry_on_timeout is True:
275
- retry_on_error.append(TimeoutError)
276
282
  kwargs = {
277
283
  "db": db,
278
284
  "username": username,
@@ -366,7 +372,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
366
372
  self.connection = None
367
373
  self._single_connection_client = single_connection_client
368
374
  if self._single_connection_client:
369
- self.connection = self.connection_pool.get_connection("_")
375
+ self.connection = self.connection_pool.get_connection()
370
376
  self._event_dispatcher.dispatch(
371
377
  AfterSingleConnectionInstantiationEvent(
372
378
  self.connection, ClientType.SYNC, self.single_connection_lock
@@ -394,10 +400,10 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
394
400
  """Get the connection's key-word arguments"""
395
401
  return self.connection_pool.connection_kwargs
396
402
 
397
- def get_retry(self) -> Optional["Retry"]:
403
+ def get_retry(self) -> Optional[Retry]:
398
404
  return self.get_connection_kwargs().get("retry")
399
405
 
400
- def set_retry(self, retry: "Retry") -> None:
406
+ def set_retry(self, retry: Retry) -> None:
401
407
  self.get_connection_kwargs().update({"retry": retry})
402
408
  self.connection_pool.set_retry(retry)
403
409
 
@@ -473,6 +479,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
473
479
  blocking_timeout: Optional[float] = None,
474
480
  lock_class: Union[None, Any] = None,
475
481
  thread_local: bool = True,
482
+ raise_on_release_error: bool = True,
476
483
  ):
477
484
  """
478
485
  Return a new Lock object using key ``name`` that mimics
@@ -519,6 +526,11 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
519
526
  thread-1 would see the token value as "xyz" and would be
520
527
  able to successfully release the thread-2's lock.
521
528
 
529
+ ``raise_on_release_error`` indicates whether to raise an exception when
530
+ the lock is no longer owned when exiting the context manager. By default,
531
+ this is True, meaning an exception will be raised. If False, the warning
532
+ will be logged and the exception will be suppressed.
533
+
522
534
  In some use cases it's necessary to disable thread local storage. For
523
535
  example, if you have code where one thread acquires a lock and passes
524
536
  that lock instance to a worker thread to release later. If thread
@@ -536,6 +548,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
536
548
  blocking=blocking,
537
549
  blocking_timeout=blocking_timeout,
538
550
  thread_local=thread_local,
551
+ raise_on_release_error=raise_on_release_error,
539
552
  )
540
553
 
541
554
  def pubsub(self, **kwargs):
@@ -563,7 +576,10 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
563
576
  self.close()
564
577
 
565
578
  def __del__(self):
566
- self.close()
579
+ try:
580
+ self.close()
581
+ except Exception:
582
+ pass
567
583
 
568
584
  def close(self) -> None:
569
585
  # In case a connection property does not yet exist
@@ -587,18 +603,18 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
587
603
  conn.send_command(*args, **options)
588
604
  return self.parse_response(conn, command_name, **options)
589
605
 
590
- def _disconnect_raise(self, conn, error):
606
+ def _close_connection(self, conn) -> None:
591
607
  """
592
- Close the connection and raise an exception
593
- if retry_on_error is not set or the error
594
- is not one of the specified error types
608
+ Close the connection before retrying.
609
+
610
+ The supported exceptions are already checked in the
611
+ retry object so we don't need to do it here.
612
+
613
+ After we disconnect the connection, it will try to reconnect and
614
+ do a health check as part of the send_command logic(on connection level).
595
615
  """
616
+
596
617
  conn.disconnect()
597
- if (
598
- conn.retry_on_error is None
599
- or isinstance(error, tuple(conn.retry_on_error)) is False
600
- ):
601
- raise error
602
618
 
603
619
  # COMMAND EXECUTION AND PROTOCOL PARSING
604
620
  def execute_command(self, *args, **options):
@@ -608,7 +624,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
608
624
  """Execute a command and return a parsed response"""
609
625
  pool = self.connection_pool
610
626
  command_name = args[0]
611
- conn = self.connection or pool.get_connection(command_name, **options)
627
+ conn = self.connection or pool.get_connection()
612
628
 
613
629
  if self._single_connection_client:
614
630
  self.single_connection_lock.acquire()
@@ -617,7 +633,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
617
633
  lambda: self._send_command_parse_response(
618
634
  conn, command_name, *args, **options
619
635
  ),
620
- lambda error: self._disconnect_raise(conn, error),
636
+ lambda _: self._close_connection(conn),
621
637
  )
622
638
  finally:
623
639
  if self._single_connection_client:
@@ -667,7 +683,7 @@ class Monitor:
667
683
 
668
684
  def __init__(self, connection_pool):
669
685
  self.connection_pool = connection_pool
670
- self.connection = self.connection_pool.get_connection("MONITOR")
686
+ self.connection = self.connection_pool.get_connection()
671
687
 
672
688
  def __enter__(self):
673
689
  self.connection.send_command("MONITOR")
@@ -840,9 +856,7 @@ class PubSub:
840
856
  # subscribed to one or more channels
841
857
 
842
858
  if self.connection is None:
843
- self.connection = self.connection_pool.get_connection(
844
- "pubsub", self.shard_hint
845
- )
859
+ self.connection = self.connection_pool.get_connection()
846
860
  # register a callback that re-subscribes to any channels we
847
861
  # were listening to when we were disconnected
848
862
  self.connection.register_connect_callback(self.on_connect)
@@ -878,19 +892,14 @@ class PubSub:
878
892
  )
879
893
  ttl -= 1
880
894
 
881
- def _disconnect_raise_connect(self, conn, error) -> None:
895
+ def _reconnect(self, conn) -> None:
882
896
  """
883
- Close the connection and raise an exception
884
- if retry_on_error is not set or the error is not one
885
- of the specified error types. Otherwise, try to
886
- reconnect
897
+ The supported exceptions are already checked in the
898
+ retry object so we don't need to do it here.
899
+
900
+ In this error handler we are trying to reconnect to the server.
887
901
  """
888
902
  conn.disconnect()
889
- if (
890
- conn.retry_on_error is None
891
- or isinstance(error, tuple(conn.retry_on_error)) is False
892
- ):
893
- raise error
894
903
  conn.connect()
895
904
 
896
905
  def _execute(self, conn, command, *args, **kwargs):
@@ -903,7 +912,7 @@ class PubSub:
903
912
  """
904
913
  return conn.retry.call_with_retry(
905
914
  lambda: command(*args, **kwargs),
906
- lambda error: self._disconnect_raise_connect(conn, error),
915
+ lambda _: self._reconnect(conn),
907
916
  )
908
917
 
909
918
  def parse_response(self, block=True, timeout=0):
@@ -952,7 +961,7 @@ class PubSub:
952
961
  "did you forget to call subscribe() or psubscribe()?"
953
962
  )
954
963
 
955
- if conn.health_check_interval and time.time() > conn.next_health_check:
964
+ if conn.health_check_interval and time.monotonic() > conn.next_health_check:
956
965
  conn.send_command("PING", self.HEALTH_CHECK_MESSAGE, check_health=False)
957
966
  self.health_check_response_counter += 1
958
967
 
@@ -1102,12 +1111,12 @@ class PubSub:
1102
1111
  """
1103
1112
  if not self.subscribed:
1104
1113
  # Wait for subscription
1105
- start_time = time.time()
1114
+ start_time = time.monotonic()
1106
1115
  if self.subscribed_event.wait(timeout) is True:
1107
1116
  # The connection was subscribed during the timeout time frame.
1108
1117
  # The timeout should be adjusted based on the time spent
1109
1118
  # waiting for the subscription
1110
- time_spent = time.time() - start_time
1119
+ time_spent = time.monotonic() - start_time
1111
1120
  timeout = max(0.0, timeout - time_spent)
1112
1121
  else:
1113
1122
  # The connection isn't subscribed to any channels or patterns,
@@ -1272,7 +1281,8 @@ class Pipeline(Redis):
1272
1281
  in one transmission. This is convenient for batch processing, such as
1273
1282
  saving all the values in a list to Redis.
1274
1283
 
1275
- All commands executed within a pipeline are wrapped with MULTI and EXEC
1284
+ All commands executed within a pipeline(when running in transactional mode,
1285
+ which is the default behavior) are wrapped with MULTI and EXEC
1276
1286
  calls. This guarantees all commands executed in the pipeline will be
1277
1287
  executed atomically.
1278
1288
 
@@ -1293,9 +1303,10 @@ class Pipeline(Redis):
1293
1303
  self.response_callbacks = response_callbacks
1294
1304
  self.transaction = transaction
1295
1305
  self.shard_hint = shard_hint
1296
-
1297
1306
  self.watching = False
1298
- self.reset()
1307
+ self.command_stack = []
1308
+ self.scripts: Set[Script] = set()
1309
+ self.explicit_transaction = False
1299
1310
 
1300
1311
  def __enter__(self) -> "Pipeline":
1301
1312
  return self
@@ -1361,50 +1372,51 @@ class Pipeline(Redis):
1361
1372
  return self.immediate_execute_command(*args, **kwargs)
1362
1373
  return self.pipeline_execute_command(*args, **kwargs)
1363
1374
 
1364
- def _disconnect_reset_raise(self, conn, error) -> None:
1375
+ def _disconnect_reset_raise_on_watching(
1376
+ self,
1377
+ conn: AbstractConnection,
1378
+ error: Exception,
1379
+ ) -> None:
1365
1380
  """
1366
- Close the connection, reset watching state and
1367
- raise an exception if we were watching,
1368
- if retry_on_error is not set or the error is not one
1369
- of the specified error types.
1381
+ Close the connection reset watching state and
1382
+ raise an exception if we were watching.
1383
+
1384
+ The supported exceptions are already checked in the
1385
+ retry object so we don't need to do it here.
1386
+
1387
+ After we disconnect the connection, it will try to reconnect and
1388
+ do a health check as part of the send_command logic(on connection level).
1370
1389
  """
1371
1390
  conn.disconnect()
1391
+
1372
1392
  # if we were already watching a variable, the watch is no longer
1373
1393
  # valid since this connection has died. raise a WatchError, which
1374
1394
  # indicates the user should retry this transaction.
1375
1395
  if self.watching:
1376
1396
  self.reset()
1377
1397
  raise WatchError(
1378
- "A ConnectionError occurred on while watching one or more keys"
1398
+ f"A {type(error).__name__} occurred while watching one or more keys"
1379
1399
  )
1380
- # if retry_on_error is not set or the error is not one
1381
- # of the specified error types, raise it
1382
- if (
1383
- conn.retry_on_error is None
1384
- or isinstance(error, tuple(conn.retry_on_error)) is False
1385
- ):
1386
- self.reset()
1387
- raise
1388
1400
 
1389
1401
  def immediate_execute_command(self, *args, **options):
1390
1402
  """
1391
- Execute a command immediately, but don't auto-retry on a
1392
- ConnectionError if we're already WATCHing a variable. Used when
1393
- issuing WATCH or subsequent commands retrieving their values but before
1403
+ Execute a command immediately, but don't auto-retry on the supported
1404
+ errors for retry if we're already WATCHing a variable.
1405
+ Used when issuing WATCH or subsequent commands retrieving their values but before
1394
1406
  MULTI is called.
1395
1407
  """
1396
1408
  command_name = args[0]
1397
1409
  conn = self.connection
1398
1410
  # if this is the first call, we need a connection
1399
1411
  if not conn:
1400
- conn = self.connection_pool.get_connection(command_name, self.shard_hint)
1412
+ conn = self.connection_pool.get_connection()
1401
1413
  self.connection = conn
1402
1414
 
1403
1415
  return conn.retry.call_with_retry(
1404
1416
  lambda: self._send_command_parse_response(
1405
1417
  conn, command_name, *args, **options
1406
1418
  ),
1407
- lambda error: self._disconnect_reset_raise(conn, error),
1419
+ lambda error: self._disconnect_reset_raise_on_watching(conn, error),
1408
1420
  )
1409
1421
 
1410
1422
  def pipeline_execute_command(self, *args, **options) -> "Pipeline":
@@ -1516,7 +1528,7 @@ class Pipeline(Redis):
1516
1528
  def annotate_exception(self, exception, number, command):
1517
1529
  cmd = " ".join(map(safe_str, command))
1518
1530
  msg = (
1519
- f"Command # {number} ({cmd}) of pipeline "
1531
+ f"Command # {number} ({truncate_text(cmd)}) of pipeline "
1520
1532
  f"caused error: {exception.args[0]}"
1521
1533
  )
1522
1534
  exception.args = (msg,) + exception.args[1:]
@@ -1542,15 +1554,19 @@ class Pipeline(Redis):
1542
1554
  if not exist:
1543
1555
  s.sha = immediate("SCRIPT LOAD", s.script)
1544
1556
 
1545
- def _disconnect_raise_reset(
1557
+ def _disconnect_raise_on_watching(
1546
1558
  self,
1547
1559
  conn: AbstractConnection,
1548
1560
  error: Exception,
1549
1561
  ) -> None:
1550
1562
  """
1551
- Close the connection, raise an exception if we were watching,
1552
- and raise an exception if retry_on_error is not set or the
1553
- error is not one of the specified error types.
1563
+ Close the connection, raise an exception if we were watching.
1564
+
1565
+ The supported exceptions are already checked in the
1566
+ retry object so we don't need to do it here.
1567
+
1568
+ After we disconnect the connection, it will try to reconnect and
1569
+ do a health check as part of the send_command logic(on connection level).
1554
1570
  """
1555
1571
  conn.disconnect()
1556
1572
  # if we were watching a variable, the watch is no longer valid
@@ -1558,16 +1574,8 @@ class Pipeline(Redis):
1558
1574
  # indicates the user should retry this transaction.
1559
1575
  if self.watching:
1560
1576
  raise WatchError(
1561
- "A ConnectionError occurred on while watching one or more keys"
1577
+ f"A {type(error).__name__} occurred while watching one or more keys"
1562
1578
  )
1563
- # if retry_on_error is not set or the error is not one
1564
- # of the specified error types, raise it
1565
- if (
1566
- conn.retry_on_error is None
1567
- or isinstance(error, tuple(conn.retry_on_error)) is False
1568
- ):
1569
- self.reset()
1570
- raise error
1571
1579
 
1572
1580
  def execute(self, raise_on_error: bool = True) -> List[Any]:
1573
1581
  """Execute all the commands in the current pipeline"""
@@ -1583,7 +1591,7 @@ class Pipeline(Redis):
1583
1591
 
1584
1592
  conn = self.connection
1585
1593
  if not conn:
1586
- conn = self.connection_pool.get_connection("MULTI", self.shard_hint)
1594
+ conn = self.connection_pool.get_connection()
1587
1595
  # assign to self.connection so reset() releases the connection
1588
1596
  # back to the pool after we're done
1589
1597
  self.connection = conn
@@ -1591,7 +1599,7 @@ class Pipeline(Redis):
1591
1599
  try:
1592
1600
  return conn.retry.call_with_retry(
1593
1601
  lambda: execute(conn, stack, raise_on_error),
1594
- lambda error: self._disconnect_raise_reset(conn, error),
1602
+ lambda error: self._disconnect_raise_on_watching(conn, error),
1595
1603
  )
1596
1604
  finally:
1597
1605
  self.reset()