redis 6.4.0__py3-none-any.whl → 7.0.0b2__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.
redis/client.py CHANGED
@@ -56,6 +56,10 @@ from redis.exceptions import (
56
56
  WatchError,
57
57
  )
58
58
  from redis.lock import Lock
59
+ from redis.maint_notifications import (
60
+ MaintNotificationsConfig,
61
+ MaintNotificationsPoolHandler,
62
+ )
59
63
  from redis.retry import Retry
60
64
  from redis.utils import (
61
65
  _set_info_logger,
@@ -220,6 +224,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
220
224
  ssl_keyfile: Optional[str] = None,
221
225
  ssl_certfile: Optional[str] = None,
222
226
  ssl_cert_reqs: Union[str, "ssl.VerifyMode"] = "required",
227
+ ssl_include_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
228
+ ssl_exclude_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
223
229
  ssl_ca_certs: Optional[str] = None,
224
230
  ssl_ca_path: Optional[str] = None,
225
231
  ssl_ca_data: Optional[str] = None,
@@ -244,6 +250,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
244
250
  cache: Optional[CacheInterface] = None,
245
251
  cache_config: Optional[CacheConfig] = None,
246
252
  event_dispatcher: Optional[EventDispatcher] = None,
253
+ maint_notifications_config: Optional[MaintNotificationsConfig] = None,
247
254
  ) -> None:
248
255
  """
249
256
  Initialize a new Redis client.
@@ -325,6 +332,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
325
332
  "ssl_keyfile": ssl_keyfile,
326
333
  "ssl_certfile": ssl_certfile,
327
334
  "ssl_cert_reqs": ssl_cert_reqs,
335
+ "ssl_include_verify_flags": ssl_include_verify_flags,
336
+ "ssl_exclude_verify_flags": ssl_exclude_verify_flags,
328
337
  "ssl_ca_certs": ssl_ca_certs,
329
338
  "ssl_ca_data": ssl_ca_data,
330
339
  "ssl_check_hostname": ssl_check_hostname,
@@ -368,6 +377,23 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
368
377
  ]:
369
378
  raise RedisError("Client caching is only supported with RESP version 3")
370
379
 
380
+ if maint_notifications_config and self.connection_pool.get_protocol() not in [
381
+ 3,
382
+ "3",
383
+ ]:
384
+ raise RedisError(
385
+ "Push handlers on connection are only supported with RESP version 3"
386
+ )
387
+ if maint_notifications_config and maint_notifications_config.enabled:
388
+ self.maint_notifications_pool_handler = MaintNotificationsPoolHandler(
389
+ self.connection_pool, maint_notifications_config
390
+ )
391
+ self.connection_pool.set_maint_notifications_pool_handler(
392
+ self.maint_notifications_pool_handler
393
+ )
394
+ else:
395
+ self.maint_notifications_pool_handler = None
396
+
371
397
  self.single_connection_lock = threading.RLock()
372
398
  self.connection = None
373
399
  self._single_connection_client = single_connection_client
@@ -565,8 +591,15 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
565
591
  return Monitor(self.connection_pool)
566
592
 
567
593
  def client(self):
594
+ maint_notifications_config = (
595
+ None
596
+ if self.maint_notifications_pool_handler is None
597
+ else self.maint_notifications_pool_handler.config
598
+ )
568
599
  return self.__class__(
569
- connection_pool=self.connection_pool, single_connection_client=True
600
+ connection_pool=self.connection_pool,
601
+ single_connection_client=True,
602
+ maint_notifications_config=maint_notifications_config,
570
603
  )
571
604
 
572
605
  def __enter__(self):
@@ -635,7 +668,11 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
635
668
  ),
636
669
  lambda _: self._close_connection(conn),
637
670
  )
671
+
638
672
  finally:
673
+ if conn and conn.should_reconnect():
674
+ self._close_connection(conn)
675
+ conn.connect()
639
676
  if self._single_connection_client:
640
677
  self.single_connection_lock.release()
641
678
  if not self.connection:
@@ -686,11 +723,7 @@ class Monitor:
686
723
  self.connection = self.connection_pool.get_connection()
687
724
 
688
725
  def __enter__(self):
689
- self.connection.send_command("MONITOR")
690
- # check that monitor returns 'OK', but don't return it to user
691
- response = self.connection.read_response()
692
- if not bool_ok(response):
693
- raise RedisError(f"MONITOR failed: {response}")
726
+ self._start_monitor()
694
727
  return self
695
728
 
696
729
  def __exit__(self, *args):
@@ -700,8 +733,13 @@ class Monitor:
700
733
  def next_command(self):
701
734
  """Parse the response from a monitor command"""
702
735
  response = self.connection.read_response()
736
+
737
+ if response is None:
738
+ return None
739
+
703
740
  if isinstance(response, bytes):
704
741
  response = self.connection.encoder.decode(response, force=True)
742
+
705
743
  command_time, command_data = response.split(" ", 1)
706
744
  m = self.monitor_re.match(command_data)
707
745
  db_id, client_info, command = m.groups()
@@ -737,6 +775,14 @@ class Monitor:
737
775
  while True:
738
776
  yield self.next_command()
739
777
 
778
+ def _start_monitor(self):
779
+ self.connection.send_command("MONITOR")
780
+ # check that monitor returns 'OK', but don't return it to user
781
+ response = self.connection.read_response()
782
+
783
+ if not bool_ok(response):
784
+ raise RedisError(f"MONITOR failed: {response}")
785
+
740
786
 
741
787
  class PubSub:
742
788
  """
@@ -881,7 +927,7 @@ class PubSub:
881
927
  """
882
928
  ttl = 10
883
929
  conn = self.connection
884
- while self.health_check_response_counter > 0 and ttl > 0:
930
+ while conn and self.health_check_response_counter > 0 and ttl > 0:
885
931
  if self._execute(conn, conn.can_read, timeout=conn.socket_timeout):
886
932
  response = self._execute(conn, conn.read_response)
887
933
  if self.is_health_check_response(response):
@@ -911,11 +957,17 @@ class PubSub:
911
957
  called by the # connection to resubscribe us to any channels and
912
958
  patterns we were previously listening to
913
959
  """
914
- return conn.retry.call_with_retry(
960
+
961
+ if conn.should_reconnect():
962
+ self._reconnect(conn)
963
+
964
+ response = conn.retry.call_with_retry(
915
965
  lambda: command(*args, **kwargs),
916
966
  lambda _: self._reconnect(conn),
917
967
  )
918
968
 
969
+ return response
970
+
919
971
  def parse_response(self, block=True, timeout=0):
920
972
  """Parse the response from a publish/subscribe command"""
921
973
  conn = self.connection
@@ -1125,6 +1177,7 @@ class PubSub:
1125
1177
  return None
1126
1178
 
1127
1179
  response = self.parse_response(block=(timeout is None), timeout=timeout)
1180
+
1128
1181
  if response:
1129
1182
  return self.handle_message(response, ignore_subscribe_messages)
1130
1183
  return None
@@ -1148,6 +1201,7 @@ class PubSub:
1148
1201
  return None
1149
1202
  if isinstance(response, bytes):
1150
1203
  response = [b"pong", response] if response != b"PONG" else [b"pong", b""]
1204
+
1151
1205
  message_type = str_if_bytes(response[0])
1152
1206
  if message_type == "pmessage":
1153
1207
  message = {
@@ -1351,6 +1405,7 @@ class Pipeline(Redis):
1351
1405
  # clean up the other instance attributes
1352
1406
  self.watching = False
1353
1407
  self.explicit_transaction = False
1408
+
1354
1409
  # we can safely return the connection to the pool here since we're
1355
1410
  # sure we're no longer WATCHing anything
1356
1411
  if self.connection:
@@ -1510,6 +1565,7 @@ class Pipeline(Redis):
1510
1565
  if command_name in self.response_callbacks:
1511
1566
  r = self.response_callbacks[command_name](r, **options)
1512
1567
  data.append(r)
1568
+
1513
1569
  return data
1514
1570
 
1515
1571
  def _execute_pipeline(self, connection, commands, raise_on_error):
@@ -1517,16 +1573,17 @@ class Pipeline(Redis):
1517
1573
  all_cmds = connection.pack_commands([args for args, _ in commands])
1518
1574
  connection.send_packed_command(all_cmds)
1519
1575
 
1520
- response = []
1576
+ responses = []
1521
1577
  for args, options in commands:
1522
1578
  try:
1523
- response.append(self.parse_response(connection, args[0], **options))
1579
+ responses.append(self.parse_response(connection, args[0], **options))
1524
1580
  except ResponseError as e:
1525
- response.append(e)
1581
+ responses.append(e)
1526
1582
 
1527
1583
  if raise_on_error:
1528
- self.raise_first_error(commands, response)
1529
- return response
1584
+ self.raise_first_error(commands, responses)
1585
+
1586
+ return responses
1530
1587
 
1531
1588
  def raise_first_error(self, commands, response):
1532
1589
  for i, r in enumerate(response):
@@ -1611,6 +1668,8 @@ class Pipeline(Redis):
1611
1668
  lambda error: self._disconnect_raise_on_watching(conn, error),
1612
1669
  )
1613
1670
  finally:
1671
+ # in reset() the connection is disconnected before returned to the pool if
1672
+ # it is marked for reconnect.
1614
1673
  self.reset()
1615
1674
 
1616
1675
  def discard(self):
redis/cluster.py CHANGED
@@ -170,6 +170,7 @@ REDIS_ALLOWED_KEYS = (
170
170
  "redis_connect_func",
171
171
  "password",
172
172
  "port",
173
+ "timeout",
173
174
  "queue_class",
174
175
  "retry",
175
176
  "retry_on_timeout",
@@ -183,6 +184,8 @@ REDIS_ALLOWED_KEYS = (
183
184
  "ssl_ca_data",
184
185
  "ssl_certfile",
185
186
  "ssl_cert_reqs",
187
+ "ssl_include_verify_flags",
188
+ "ssl_exclude_verify_flags",
186
189
  "ssl_keyfile",
187
190
  "ssl_password",
188
191
  "ssl_check_hostname",
@@ -2716,8 +2719,8 @@ class PipelineStrategy(AbstractStrategy):
2716
2719
 
2717
2720
  If one of the retryable exceptions has been thrown we assume that:
2718
2721
  - connection_pool was disconnected
2719
- - connection_pool was reseted
2720
- - refereh_table_asap set to True
2722
+ - connection_pool was reset
2723
+ - refresh_table_asap set to True
2721
2724
 
2722
2725
  It will try the number of times specified by
2723
2726
  the retries in config option "self.retry"