redis 7.0.0b1__tar.gz → 7.0.0b2__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 (166) hide show
  1. {redis-7.0.0b1 → redis-7.0.0b2}/PKG-INFO +1 -1
  2. {redis-7.0.0b1 → redis-7.0.0b2}/redis/__init__.py +1 -1
  3. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/base.py +36 -22
  4. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/client.py +6 -1
  5. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/cluster.py +6 -1
  6. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/connection.py +43 -1
  7. {redis-7.0.0b1 → redis-7.0.0b2}/redis/client.py +19 -15
  8. {redis-7.0.0b1 → redis-7.0.0b2}/redis/cluster.py +2 -0
  9. {redis-7.0.0b1 → redis-7.0.0b2}/redis/connection.py +206 -151
  10. redis-7.0.0b1/redis/maintenance_events.py → redis-7.0.0b2/redis/maint_notifications.py +154 -140
  11. redis-7.0.0b2/tests/test_asyncio/test_ssl.py +143 -0
  12. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_connection_pool.py +62 -2
  13. redis-7.0.0b2/tests/test_maint_notifications.py +893 -0
  14. redis-7.0.0b1/tests/test_maintenance_events_handling.py → redis-7.0.0b2/tests/test_maint_notifications_handling.py +376 -325
  15. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_scenario/conftest.py +27 -22
  16. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_scenario/fault_injector_client.py +3 -2
  17. redis-7.0.0b1/tests/test_scenario/hitless_upgrade_helpers.py → redis-7.0.0b2/tests/test_scenario/maint_notifications_helpers.py +39 -0
  18. redis-7.0.0b1/tests/test_scenario/test_hitless_upgrade.py → redis-7.0.0b2/tests/test_scenario/test_maint_notifications.py +389 -73
  19. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_ssl.py +97 -0
  20. redis-7.0.0b1/tests/test_asyncio/test_ssl.py +0 -56
  21. redis-7.0.0b1/tests/test_maintenance_events.py +0 -869
  22. {redis-7.0.0b1 → redis-7.0.0b2}/.gitignore +0 -0
  23. {redis-7.0.0b1 → redis-7.0.0b2}/LICENSE +0 -0
  24. {redis-7.0.0b1 → redis-7.0.0b2}/README.md +0 -0
  25. {redis-7.0.0b1 → redis-7.0.0b2}/dev_requirements.txt +0 -0
  26. {redis-7.0.0b1 → redis-7.0.0b2}/pyproject.toml +0 -0
  27. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/__init__.py +0 -0
  28. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/commands.py +0 -0
  29. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/encoders.py +0 -0
  30. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/helpers.py +0 -0
  31. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/hiredis.py +0 -0
  32. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/resp2.py +0 -0
  33. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/resp3.py +0 -0
  34. {redis-7.0.0b1 → redis-7.0.0b2}/redis/_parsers/socket.py +0 -0
  35. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/__init__.py +0 -0
  36. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/lock.py +0 -0
  37. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/retry.py +0 -0
  38. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/sentinel.py +0 -0
  39. {redis-7.0.0b1 → redis-7.0.0b2}/redis/asyncio/utils.py +0 -0
  40. {redis-7.0.0b1 → redis-7.0.0b2}/redis/auth/__init__.py +0 -0
  41. {redis-7.0.0b1 → redis-7.0.0b2}/redis/auth/err.py +0 -0
  42. {redis-7.0.0b1 → redis-7.0.0b2}/redis/auth/idp.py +0 -0
  43. {redis-7.0.0b1 → redis-7.0.0b2}/redis/auth/token.py +0 -0
  44. {redis-7.0.0b1 → redis-7.0.0b2}/redis/auth/token_manager.py +0 -0
  45. {redis-7.0.0b1 → redis-7.0.0b2}/redis/backoff.py +0 -0
  46. {redis-7.0.0b1 → redis-7.0.0b2}/redis/cache.py +0 -0
  47. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/__init__.py +0 -0
  48. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/bf/__init__.py +0 -0
  49. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/bf/commands.py +0 -0
  50. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/bf/info.py +0 -0
  51. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/cluster.py +0 -0
  52. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/core.py +0 -0
  53. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/helpers.py +0 -0
  54. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/json/__init__.py +0 -0
  55. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/json/_util.py +0 -0
  56. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/json/commands.py +0 -0
  57. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/json/decoders.py +0 -0
  58. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/json/path.py +0 -0
  59. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/redismodules.py +0 -0
  60. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/__init__.py +0 -0
  61. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/_util.py +0 -0
  62. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/aggregation.py +0 -0
  63. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/commands.py +0 -0
  64. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/dialect.py +0 -0
  65. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/document.py +0 -0
  66. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/field.py +0 -0
  67. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/index_definition.py +0 -0
  68. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/profile_information.py +0 -0
  69. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/query.py +0 -0
  70. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/querystring.py +0 -0
  71. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/reducers.py +0 -0
  72. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/result.py +0 -0
  73. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/search/suggestion.py +0 -0
  74. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/sentinel.py +0 -0
  75. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/timeseries/__init__.py +0 -0
  76. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/timeseries/commands.py +0 -0
  77. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/timeseries/info.py +0 -0
  78. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/timeseries/utils.py +0 -0
  79. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/vectorset/__init__.py +0 -0
  80. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/vectorset/commands.py +0 -0
  81. {redis-7.0.0b1 → redis-7.0.0b2}/redis/commands/vectorset/utils.py +0 -0
  82. {redis-7.0.0b1 → redis-7.0.0b2}/redis/crc.py +0 -0
  83. {redis-7.0.0b1 → redis-7.0.0b2}/redis/credentials.py +0 -0
  84. {redis-7.0.0b1 → redis-7.0.0b2}/redis/event.py +0 -0
  85. {redis-7.0.0b1 → redis-7.0.0b2}/redis/exceptions.py +0 -0
  86. {redis-7.0.0b1 → redis-7.0.0b2}/redis/lock.py +0 -0
  87. {redis-7.0.0b1 → redis-7.0.0b2}/redis/ocsp.py +0 -0
  88. {redis-7.0.0b1 → redis-7.0.0b2}/redis/py.typed +0 -0
  89. {redis-7.0.0b1 → redis-7.0.0b2}/redis/retry.py +0 -0
  90. {redis-7.0.0b1 → redis-7.0.0b2}/redis/sentinel.py +0 -0
  91. {redis-7.0.0b1 → redis-7.0.0b2}/redis/typing.py +0 -0
  92. {redis-7.0.0b1 → redis-7.0.0b2}/redis/utils.py +0 -0
  93. {redis-7.0.0b1 → redis-7.0.0b2}/tests/__init__.py +0 -0
  94. {redis-7.0.0b1 → redis-7.0.0b2}/tests/conftest.py +0 -0
  95. {redis-7.0.0b1 → redis-7.0.0b2}/tests/entraid_utils.py +0 -0
  96. {redis-7.0.0b1 → redis-7.0.0b2}/tests/mocks.py +0 -0
  97. {redis-7.0.0b1 → redis-7.0.0b2}/tests/ssl_utils.py +0 -0
  98. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/__init__.py +0 -0
  99. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/compat.py +0 -0
  100. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/conftest.py +0 -0
  101. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/mocks.py +0 -0
  102. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_bloom.py +0 -0
  103. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_cluster.py +0 -0
  104. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_cluster_transaction.py +0 -0
  105. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_commands.py +0 -0
  106. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_connect.py +0 -0
  107. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_connection.py +0 -0
  108. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_connection_pool.py +0 -0
  109. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_credentials.py +0 -0
  110. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_cwe_404.py +0 -0
  111. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_encoding.py +0 -0
  112. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_hash.py +0 -0
  113. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_json.py +0 -0
  114. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_lock.py +0 -0
  115. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_monitor.py +0 -0
  116. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_pipeline.py +0 -0
  117. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_pubsub.py +0 -0
  118. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_retry.py +0 -0
  119. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_scripting.py +0 -0
  120. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_search.py +0 -0
  121. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_sentinel.py +0 -0
  122. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_sentinel_managed_connection.py +0 -0
  123. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_timeseries.py +0 -0
  124. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_usage_counter.py +0 -0
  125. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_utils.py +0 -0
  126. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/test_vsets.py +0 -0
  127. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/testdata/jsontestdata.py +0 -0
  128. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/testdata/titles.csv +0 -0
  129. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_asyncio/testdata/will_play_text.csv.bz2 +0 -0
  130. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_auth/__init__.py +0 -0
  131. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_auth/test_token.py +0 -0
  132. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_auth/test_token_manager.py +0 -0
  133. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_backoff.py +0 -0
  134. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_bloom.py +0 -0
  135. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_cache.py +0 -0
  136. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_cluster.py +0 -0
  137. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_cluster_transaction.py +0 -0
  138. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_command_parser.py +0 -0
  139. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_commands.py +0 -0
  140. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_connect.py +0 -0
  141. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_connection.py +0 -0
  142. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_credentials.py +0 -0
  143. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_encoding.py +0 -0
  144. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_function.py +0 -0
  145. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_hash.py +0 -0
  146. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_helpers.py +0 -0
  147. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_json.py +0 -0
  148. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_lock.py +0 -0
  149. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_max_connections_error.py +0 -0
  150. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_monitor.py +0 -0
  151. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_multiprocessing.py +0 -0
  152. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_parsers/test_helpers.py +0 -0
  153. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_pipeline.py +0 -0
  154. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_pubsub.py +0 -0
  155. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_retry.py +0 -0
  156. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_scenario/__init__.py +0 -0
  157. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_scripting.py +0 -0
  158. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_search.py +0 -0
  159. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_sentinel.py +0 -0
  160. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_sentinel_managed_connection.py +0 -0
  161. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_timeseries.py +0 -0
  162. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_utils.py +0 -0
  163. {redis-7.0.0b1 → redis-7.0.0b2}/tests/test_vsets.py +0 -0
  164. {redis-7.0.0b1 → redis-7.0.0b2}/tests/testdata/jsontestdata.py +0 -0
  165. {redis-7.0.0b1 → redis-7.0.0b2}/tests/testdata/titles.csv +0 -0
  166. {redis-7.0.0b1 → redis-7.0.0b2}/tests/testdata/will_play_text.csv.bz2 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis
3
- Version: 7.0.0b1
3
+ Version: 7.0.0b2
4
4
  Summary: Python client for Redis database and key-value store
5
5
  Project-URL: Changes, https://github.com/redis/redis-py/releases
6
6
  Project-URL: Code, https://github.com/redis/redis-py
@@ -46,7 +46,7 @@ def int_or_str(value):
46
46
  return value
47
47
 
48
48
 
49
- __version__ = "7.0.0b1"
49
+ __version__ = "7.0.0b2"
50
50
  VERSION = tuple(map(int_or_str, __version__.split(".")))
51
51
 
52
52
 
@@ -4,13 +4,13 @@ from abc import ABC
4
4
  from asyncio import IncompleteReadError, StreamReader, TimeoutError
5
5
  from typing import Awaitable, Callable, List, Optional, Protocol, Union
6
6
 
7
- from redis.maintenance_events import (
8
- MaintenanceEvent,
9
- NodeFailedOverEvent,
10
- NodeFailingOverEvent,
11
- NodeMigratedEvent,
12
- NodeMigratingEvent,
13
- NodeMovingEvent,
7
+ from redis.maint_notifications import (
8
+ MaintenanceNotification,
9
+ NodeFailedOverNotification,
10
+ NodeFailingOverNotification,
11
+ NodeMigratedNotification,
12
+ NodeMigratingNotification,
13
+ NodeMovingNotification,
14
14
  )
15
15
 
16
16
  if sys.version_info.major >= 3 and sys.version_info.minor >= 11:
@@ -175,14 +175,14 @@ class MaintenanceNotificationsParser:
175
175
 
176
176
  @staticmethod
177
177
  def parse_maintenance_start_msg(response, notification_type):
178
- # Expected message format is: <event_type> <seq_number> <time>
178
+ # Expected message format is: <notification_type> <seq_number> <time>
179
179
  id = response[1]
180
180
  ttl = response[2]
181
181
  return notification_type(id, ttl)
182
182
 
183
183
  @staticmethod
184
184
  def parse_maintenance_completed_msg(response, notification_type):
185
- # Expected message format is: <event_type> <seq_number>
185
+ # Expected message format is: <notification_type> <seq_number>
186
186
  id = response[1]
187
187
  return notification_type(id)
188
188
 
@@ -200,7 +200,7 @@ class MaintenanceNotificationsParser:
200
200
  host, port = value.split(":")
201
201
  port = int(port) if port is not None else None
202
202
 
203
- return NodeMovingEvent(id, host, port, ttl)
203
+ return NodeMovingNotification(id, host, port, ttl)
204
204
 
205
205
 
206
206
  _INVALIDATION_MESSAGE = "invalidate"
@@ -217,25 +217,27 @@ _MAINTENANCE_MESSAGES = (
217
217
  _FAILED_OVER_MESSAGE,
218
218
  )
219
219
 
220
- MSG_TYPE_TO_EVENT_PARSER_MAPPING: dict[str, tuple[type[MaintenanceEvent], Callable]] = {
220
+ MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING: dict[
221
+ str, tuple[type[MaintenanceNotification], Callable]
222
+ ] = {
221
223
  _MIGRATING_MESSAGE: (
222
- NodeMigratingEvent,
224
+ NodeMigratingNotification,
223
225
  MaintenanceNotificationsParser.parse_maintenance_start_msg,
224
226
  ),
225
227
  _MIGRATED_MESSAGE: (
226
- NodeMigratedEvent,
228
+ NodeMigratedNotification,
227
229
  MaintenanceNotificationsParser.parse_maintenance_completed_msg,
228
230
  ),
229
231
  _FAILING_OVER_MESSAGE: (
230
- NodeFailingOverEvent,
232
+ NodeFailingOverNotification,
231
233
  MaintenanceNotificationsParser.parse_maintenance_start_msg,
232
234
  ),
233
235
  _FAILED_OVER_MESSAGE: (
234
- NodeFailedOverEvent,
236
+ NodeFailedOverNotification,
235
237
  MaintenanceNotificationsParser.parse_maintenance_completed_msg,
236
238
  ),
237
239
  _MOVING_MESSAGE: (
238
- NodeMovingEvent,
240
+ NodeMovingNotification,
239
241
  MaintenanceNotificationsParser.parse_moving_msg,
240
242
  ),
241
243
  }
@@ -273,14 +275,20 @@ class PushNotificationsParser(Protocol):
273
275
  return self.invalidation_push_handler_func(response)
274
276
 
275
277
  if msg_type == _MOVING_MESSAGE and self.node_moving_push_handler_func:
276
- parser_function = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][1]
278
+ parser_function = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
279
+ msg_type
280
+ ][1]
277
281
 
278
282
  notification = parser_function(response)
279
283
  return self.node_moving_push_handler_func(notification)
280
284
 
281
285
  if msg_type in _MAINTENANCE_MESSAGES and self.maintenance_push_handler_func:
282
- parser_function = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][1]
283
- notification_type = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][0]
286
+ parser_function = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
287
+ msg_type
288
+ ][1]
289
+ notification_type = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
290
+ msg_type
291
+ ][0]
284
292
  notification = parser_function(response, notification_type)
285
293
 
286
294
  if notification is not None:
@@ -342,13 +350,19 @@ class AsyncPushNotificationsParser(Protocol):
342
350
  msg_type = msg_type.decode()
343
351
 
344
352
  if msg_type == _MOVING_MESSAGE and self.node_moving_push_handler_func:
345
- parser_function = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][1]
353
+ parser_function = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
354
+ msg_type
355
+ ][1]
346
356
  notification = parser_function(response)
347
357
  return await self.node_moving_push_handler_func(notification)
348
358
 
349
359
  if msg_type in _MAINTENANCE_MESSAGES and self.maintenance_push_handler_func:
350
- parser_function = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][1]
351
- notification_type = MSG_TYPE_TO_EVENT_PARSER_MAPPING[msg_type][0]
360
+ parser_function = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
361
+ msg_type
362
+ ][1]
363
+ notification_type = MSG_TYPE_TO_MAINT_NOTIFICATION_PARSER_MAPPING[
364
+ msg_type
365
+ ][0]
352
366
  notification = parser_function(response, notification_type)
353
367
 
354
368
  if notification is not None:
@@ -81,10 +81,11 @@ from redis.utils import (
81
81
  )
82
82
 
83
83
  if TYPE_CHECKING and SSL_AVAILABLE:
84
- from ssl import TLSVersion, VerifyMode
84
+ from ssl import TLSVersion, VerifyFlags, VerifyMode
85
85
  else:
86
86
  TLSVersion = None
87
87
  VerifyMode = None
88
+ VerifyFlags = None
88
89
 
89
90
  PubSubHandler = Callable[[Dict[str, str]], Awaitable[None]]
90
91
  _KeyT = TypeVar("_KeyT", bound=KeyT)
@@ -238,6 +239,8 @@ class Redis(
238
239
  ssl_keyfile: Optional[str] = None,
239
240
  ssl_certfile: Optional[str] = None,
240
241
  ssl_cert_reqs: Union[str, VerifyMode] = "required",
242
+ ssl_include_verify_flags: Optional[List[VerifyFlags]] = None,
243
+ ssl_exclude_verify_flags: Optional[List[VerifyFlags]] = None,
241
244
  ssl_ca_certs: Optional[str] = None,
242
245
  ssl_ca_data: Optional[str] = None,
243
246
  ssl_check_hostname: bool = True,
@@ -347,6 +350,8 @@ class Redis(
347
350
  "ssl_keyfile": ssl_keyfile,
348
351
  "ssl_certfile": ssl_certfile,
349
352
  "ssl_cert_reqs": ssl_cert_reqs,
353
+ "ssl_include_verify_flags": ssl_include_verify_flags,
354
+ "ssl_exclude_verify_flags": ssl_exclude_verify_flags,
350
355
  "ssl_ca_certs": ssl_ca_certs,
351
356
  "ssl_ca_data": ssl_ca_data,
352
357
  "ssl_check_hostname": ssl_check_hostname,
@@ -86,10 +86,11 @@ from redis.utils import (
86
86
  )
87
87
 
88
88
  if SSL_AVAILABLE:
89
- from ssl import TLSVersion, VerifyMode
89
+ from ssl import TLSVersion, VerifyFlags, VerifyMode
90
90
  else:
91
91
  TLSVersion = None
92
92
  VerifyMode = None
93
+ VerifyFlags = None
93
94
 
94
95
  TargetNodesT = TypeVar(
95
96
  "TargetNodesT", str, "ClusterNode", List["ClusterNode"], Dict[Any, "ClusterNode"]
@@ -299,6 +300,8 @@ class RedisCluster(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommand
299
300
  ssl_ca_certs: Optional[str] = None,
300
301
  ssl_ca_data: Optional[str] = None,
301
302
  ssl_cert_reqs: Union[str, VerifyMode] = "required",
303
+ ssl_include_verify_flags: Optional[List[VerifyFlags]] = None,
304
+ ssl_exclude_verify_flags: Optional[List[VerifyFlags]] = None,
302
305
  ssl_certfile: Optional[str] = None,
303
306
  ssl_check_hostname: bool = True,
304
307
  ssl_keyfile: Optional[str] = None,
@@ -358,6 +361,8 @@ class RedisCluster(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommand
358
361
  "ssl_ca_certs": ssl_ca_certs,
359
362
  "ssl_ca_data": ssl_ca_data,
360
363
  "ssl_cert_reqs": ssl_cert_reqs,
364
+ "ssl_include_verify_flags": ssl_include_verify_flags,
365
+ "ssl_exclude_verify_flags": ssl_exclude_verify_flags,
361
366
  "ssl_certfile": ssl_certfile,
362
367
  "ssl_check_hostname": ssl_check_hostname,
363
368
  "ssl_keyfile": ssl_keyfile,
@@ -30,11 +30,12 @@ from ..utils import SSL_AVAILABLE
30
30
 
31
31
  if SSL_AVAILABLE:
32
32
  import ssl
33
- from ssl import SSLContext, TLSVersion
33
+ from ssl import SSLContext, TLSVersion, VerifyFlags
34
34
  else:
35
35
  ssl = None
36
36
  TLSVersion = None
37
37
  SSLContext = None
38
+ VerifyFlags = None
38
39
 
39
40
  from ..auth.token import TokenInterface
40
41
  from ..event import AsyncAfterConnectionReleasedEvent, EventDispatcher
@@ -793,6 +794,8 @@ class SSLConnection(Connection):
793
794
  ssl_keyfile: Optional[str] = None,
794
795
  ssl_certfile: Optional[str] = None,
795
796
  ssl_cert_reqs: Union[str, ssl.VerifyMode] = "required",
797
+ ssl_include_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
798
+ ssl_exclude_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
796
799
  ssl_ca_certs: Optional[str] = None,
797
800
  ssl_ca_data: Optional[str] = None,
798
801
  ssl_check_hostname: bool = True,
@@ -807,6 +810,8 @@ class SSLConnection(Connection):
807
810
  keyfile=ssl_keyfile,
808
811
  certfile=ssl_certfile,
809
812
  cert_reqs=ssl_cert_reqs,
813
+ include_verify_flags=ssl_include_verify_flags,
814
+ exclude_verify_flags=ssl_exclude_verify_flags,
810
815
  ca_certs=ssl_ca_certs,
811
816
  ca_data=ssl_ca_data,
812
817
  check_hostname=ssl_check_hostname,
@@ -832,6 +837,14 @@ class SSLConnection(Connection):
832
837
  def cert_reqs(self):
833
838
  return self.ssl_context.cert_reqs
834
839
 
840
+ @property
841
+ def include_verify_flags(self):
842
+ return self.ssl_context.include_verify_flags
843
+
844
+ @property
845
+ def exclude_verify_flags(self):
846
+ return self.ssl_context.exclude_verify_flags
847
+
835
848
  @property
836
849
  def ca_certs(self):
837
850
  return self.ssl_context.ca_certs
@@ -854,6 +867,8 @@ class RedisSSLContext:
854
867
  "keyfile",
855
868
  "certfile",
856
869
  "cert_reqs",
870
+ "include_verify_flags",
871
+ "exclude_verify_flags",
857
872
  "ca_certs",
858
873
  "ca_data",
859
874
  "context",
@@ -867,6 +882,8 @@ class RedisSSLContext:
867
882
  keyfile: Optional[str] = None,
868
883
  certfile: Optional[str] = None,
869
884
  cert_reqs: Optional[Union[str, ssl.VerifyMode]] = None,
885
+ include_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
886
+ exclude_verify_flags: Optional[List["ssl.VerifyFlags"]] = None,
870
887
  ca_certs: Optional[str] = None,
871
888
  ca_data: Optional[str] = None,
872
889
  check_hostname: bool = False,
@@ -892,6 +909,8 @@ class RedisSSLContext:
892
909
  )
893
910
  cert_reqs = CERT_REQS[cert_reqs]
894
911
  self.cert_reqs = cert_reqs
912
+ self.include_verify_flags = include_verify_flags
913
+ self.exclude_verify_flags = exclude_verify_flags
895
914
  self.ca_certs = ca_certs
896
915
  self.ca_data = ca_data
897
916
  self.check_hostname = (
@@ -906,6 +925,12 @@ class RedisSSLContext:
906
925
  context = ssl.create_default_context()
907
926
  context.check_hostname = self.check_hostname
908
927
  context.verify_mode = self.cert_reqs
928
+ if self.include_verify_flags:
929
+ for flag in self.include_verify_flags:
930
+ context.verify_flags |= flag
931
+ if self.exclude_verify_flags:
932
+ for flag in self.exclude_verify_flags:
933
+ context.verify_flags &= ~flag
909
934
  if self.certfile and self.keyfile:
910
935
  context.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile)
911
936
  if self.ca_certs or self.ca_data:
@@ -953,6 +978,20 @@ def to_bool(value) -> Optional[bool]:
953
978
  return bool(value)
954
979
 
955
980
 
981
+ def parse_ssl_verify_flags(value):
982
+ # flags are passed in as a string representation of a list,
983
+ # e.g. VERIFY_X509_STRICT, VERIFY_X509_PARTIAL_CHAIN
984
+ verify_flags_str = value.replace("[", "").replace("]", "")
985
+
986
+ verify_flags = []
987
+ for flag in verify_flags_str.split(","):
988
+ flag = flag.strip()
989
+ if not hasattr(VerifyFlags, flag):
990
+ raise ValueError(f"Invalid ssl verify flag: {flag}")
991
+ verify_flags.append(getattr(VerifyFlags, flag))
992
+ return verify_flags
993
+
994
+
956
995
  URL_QUERY_ARGUMENT_PARSERS: Mapping[str, Callable[..., object]] = MappingProxyType(
957
996
  {
958
997
  "db": int,
@@ -963,6 +1002,8 @@ URL_QUERY_ARGUMENT_PARSERS: Mapping[str, Callable[..., object]] = MappingProxyTy
963
1002
  "max_connections": int,
964
1003
  "health_check_interval": int,
965
1004
  "ssl_check_hostname": to_bool,
1005
+ "ssl_include_verify_flags": parse_ssl_verify_flags,
1006
+ "ssl_exclude_verify_flags": parse_ssl_verify_flags,
966
1007
  "timeout": float,
967
1008
  }
968
1009
  )
@@ -1021,6 +1062,7 @@ def parse_url(url: str) -> ConnectKwargs:
1021
1062
 
1022
1063
  if parsed.scheme == "rediss":
1023
1064
  kwargs["connection_class"] = SSLConnection
1065
+
1024
1066
  else:
1025
1067
  valid_schemes = "redis://, rediss://, unix://"
1026
1068
  raise ValueError(
@@ -56,9 +56,9 @@ from redis.exceptions import (
56
56
  WatchError,
57
57
  )
58
58
  from redis.lock import Lock
59
- from redis.maintenance_events import (
60
- MaintenanceEventPoolHandler,
61
- MaintenanceEventsConfig,
59
+ from redis.maint_notifications import (
60
+ MaintNotificationsConfig,
61
+ MaintNotificationsPoolHandler,
62
62
  )
63
63
  from redis.retry import Retry
64
64
  from redis.utils import (
@@ -224,6 +224,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
224
224
  ssl_keyfile: Optional[str] = None,
225
225
  ssl_certfile: Optional[str] = None,
226
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,
227
229
  ssl_ca_certs: Optional[str] = None,
228
230
  ssl_ca_path: Optional[str] = None,
229
231
  ssl_ca_data: Optional[str] = None,
@@ -248,7 +250,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
248
250
  cache: Optional[CacheInterface] = None,
249
251
  cache_config: Optional[CacheConfig] = None,
250
252
  event_dispatcher: Optional[EventDispatcher] = None,
251
- maintenance_events_config: Optional[MaintenanceEventsConfig] = None,
253
+ maint_notifications_config: Optional[MaintNotificationsConfig] = None,
252
254
  ) -> None:
253
255
  """
254
256
  Initialize a new Redis client.
@@ -330,6 +332,8 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
330
332
  "ssl_keyfile": ssl_keyfile,
331
333
  "ssl_certfile": ssl_certfile,
332
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,
333
337
  "ssl_ca_certs": ssl_ca_certs,
334
338
  "ssl_ca_data": ssl_ca_data,
335
339
  "ssl_check_hostname": ssl_check_hostname,
@@ -373,22 +377,22 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
373
377
  ]:
374
378
  raise RedisError("Client caching is only supported with RESP version 3")
375
379
 
376
- if maintenance_events_config and self.connection_pool.get_protocol() not in [
380
+ if maint_notifications_config and self.connection_pool.get_protocol() not in [
377
381
  3,
378
382
  "3",
379
383
  ]:
380
384
  raise RedisError(
381
385
  "Push handlers on connection are only supported with RESP version 3"
382
386
  )
383
- if maintenance_events_config and maintenance_events_config.enabled:
384
- self.maintenance_events_pool_handler = MaintenanceEventPoolHandler(
385
- self.connection_pool, maintenance_events_config
387
+ if maint_notifications_config and maint_notifications_config.enabled:
388
+ self.maint_notifications_pool_handler = MaintNotificationsPoolHandler(
389
+ self.connection_pool, maint_notifications_config
386
390
  )
387
- self.connection_pool.set_maintenance_events_pool_handler(
388
- self.maintenance_events_pool_handler
391
+ self.connection_pool.set_maint_notifications_pool_handler(
392
+ self.maint_notifications_pool_handler
389
393
  )
390
394
  else:
391
- self.maintenance_events_pool_handler = None
395
+ self.maint_notifications_pool_handler = None
392
396
 
393
397
  self.single_connection_lock = threading.RLock()
394
398
  self.connection = None
@@ -587,15 +591,15 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
587
591
  return Monitor(self.connection_pool)
588
592
 
589
593
  def client(self):
590
- maintenance_events_config = (
594
+ maint_notifications_config = (
591
595
  None
592
- if self.maintenance_events_pool_handler is None
593
- else self.maintenance_events_pool_handler.config
596
+ if self.maint_notifications_pool_handler is None
597
+ else self.maint_notifications_pool_handler.config
594
598
  )
595
599
  return self.__class__(
596
600
  connection_pool=self.connection_pool,
597
601
  single_connection_client=True,
598
- maintenance_events_config=maintenance_events_config,
602
+ maint_notifications_config=maint_notifications_config,
599
603
  )
600
604
 
601
605
  def __enter__(self):
@@ -184,6 +184,8 @@ REDIS_ALLOWED_KEYS = (
184
184
  "ssl_ca_data",
185
185
  "ssl_certfile",
186
186
  "ssl_cert_reqs",
187
+ "ssl_include_verify_flags",
188
+ "ssl_exclude_verify_flags",
187
189
  "ssl_keyfile",
188
190
  "ssl_password",
189
191
  "ssl_check_hostname",