redis 6.0.0b1__tar.gz → 6.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.
- {redis-6.0.0b1 → redis-6.0.0b2}/PKG-INFO +1 -1
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/__init__.py +1 -1
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/client.py +8 -3
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/cluster.py +7 -4
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/connection.py +36 -12
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/sentinel.py +2 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/client.py +4 -2
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/cluster.py +3 -1
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/core.py +1 -1
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/redismodules.py +8 -0
- redis-6.0.0b2/redis/commands/vectorset/__init__.py +46 -0
- redis-6.0.0b2/redis/commands/vectorset/commands.py +367 -0
- redis-6.0.0b2/redis/commands/vectorset/utils.py +94 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/connection.py +39 -8
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/sentinel.py +2 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/utils.py +7 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_cluster.py +19 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_pipeline.py +16 -0
- redis-6.0.0b2/tests/test_asyncio/test_vsets.py +858 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_cluster.py +19 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_pipeline.py +16 -0
- redis-6.0.0b2/tests/test_vsets.py +856 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/.gitignore +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/LICENSE +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/README.md +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/dev_requirements.txt +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/pyproject.toml +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/base.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/encoders.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/helpers.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/hiredis.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/resp2.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/resp3.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/_parsers/socket.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/lock.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/retry.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/asyncio/utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/auth/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/auth/err.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/auth/idp.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/auth/token.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/auth/token_manager.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/backoff.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/cache.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/bf/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/bf/commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/bf/info.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/cluster.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/helpers.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/json/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/json/_util.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/json/commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/json/decoders.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/json/path.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/_util.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/aggregation.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/dialect.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/document.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/field.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/index_definition.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/profile_information.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/query.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/querystring.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/reducers.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/result.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/search/suggestion.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/sentinel.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/timeseries/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/timeseries/commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/timeseries/info.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/commands/timeseries/utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/crc.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/credentials.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/event.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/exceptions.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/lock.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/ocsp.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/py.typed +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/retry.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/redis/typing.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/conftest.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/entraid_utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/mocks.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/ssl_utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/compat.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/conftest.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/mocks.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_bloom.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_connect.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_connection.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_connection_pool.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_credentials.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_cwe_404.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_encoding.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_hash.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_json.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_lock.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_monitor.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_pubsub.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_retry.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_scripting.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_search.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_sentinel.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_sentinel_managed_connection.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_timeseries.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/test_utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/testdata/jsontestdata.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/testdata/titles.csv +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_asyncio/testdata/will_play_text.csv.bz2 +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_auth/__init__.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_auth/test_token.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_auth/test_token_manager.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_backoff.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_bloom.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_cache.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_command_parser.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_commands.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_connect.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_connection.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_connection_pool.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_credentials.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_encoding.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_function.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_hash.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_helpers.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_json.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_lock.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_monitor.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_multiprocessing.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_parsers/test_helpers.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_pubsub.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_retry.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_scripting.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_search.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_sentinel.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_ssl.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_timeseries.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/test_utils.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/testdata/jsontestdata.py +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/testdata/titles.csv +0 -0
- {redis-6.0.0b1 → redis-6.0.0b2}/tests/testdata/will_play_text.csv.bz2 +0 -0
|
@@ -77,12 +77,14 @@ from redis.utils import (
|
|
|
77
77
|
get_lib_version,
|
|
78
78
|
safe_str,
|
|
79
79
|
str_if_bytes,
|
|
80
|
+
truncate_text,
|
|
80
81
|
)
|
|
81
82
|
|
|
82
83
|
if TYPE_CHECKING and SSL_AVAILABLE:
|
|
83
|
-
from ssl import TLSVersion
|
|
84
|
+
from ssl import TLSVersion, VerifyMode
|
|
84
85
|
else:
|
|
85
86
|
TLSVersion = None
|
|
87
|
+
VerifyMode = None
|
|
86
88
|
|
|
87
89
|
PubSubHandler = Callable[[Dict[str, str]], Awaitable[None]]
|
|
88
90
|
_KeyT = TypeVar("_KeyT", bound=KeyT)
|
|
@@ -227,7 +229,7 @@ class Redis(
|
|
|
227
229
|
ssl: bool = False,
|
|
228
230
|
ssl_keyfile: Optional[str] = None,
|
|
229
231
|
ssl_certfile: Optional[str] = None,
|
|
230
|
-
ssl_cert_reqs: str = "required",
|
|
232
|
+
ssl_cert_reqs: Union[str, VerifyMode] = "required",
|
|
231
233
|
ssl_ca_certs: Optional[str] = None,
|
|
232
234
|
ssl_ca_data: Optional[str] = None,
|
|
233
235
|
ssl_check_hostname: bool = False,
|
|
@@ -1513,7 +1515,10 @@ class Pipeline(Redis): # lgtm [py/init-calls-subclass]
|
|
|
1513
1515
|
self, exception: Exception, number: int, command: Iterable[object]
|
|
1514
1516
|
) -> None:
|
|
1515
1517
|
cmd = " ".join(map(safe_str, command))
|
|
1516
|
-
msg =
|
|
1518
|
+
msg = (
|
|
1519
|
+
f"Command # {number} ({truncate_text(cmd)}) "
|
|
1520
|
+
"of pipeline caused error: {exception.args}"
|
|
1521
|
+
)
|
|
1517
1522
|
exception.args = (msg,) + exception.args[1:]
|
|
1518
1523
|
|
|
1519
1524
|
async def parse_response(
|
|
@@ -71,12 +71,14 @@ from redis.utils import (
|
|
|
71
71
|
get_lib_version,
|
|
72
72
|
safe_str,
|
|
73
73
|
str_if_bytes,
|
|
74
|
+
truncate_text,
|
|
74
75
|
)
|
|
75
76
|
|
|
76
77
|
if SSL_AVAILABLE:
|
|
77
|
-
from ssl import TLSVersion
|
|
78
|
+
from ssl import TLSVersion, VerifyMode
|
|
78
79
|
else:
|
|
79
80
|
TLSVersion = None
|
|
81
|
+
VerifyMode = None
|
|
80
82
|
|
|
81
83
|
TargetNodesT = TypeVar(
|
|
82
84
|
"TargetNodesT", str, "ClusterNode", List["ClusterNode"], Dict[Any, "ClusterNode"]
|
|
@@ -267,7 +269,7 @@ class RedisCluster(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommand
|
|
|
267
269
|
ssl: bool = False,
|
|
268
270
|
ssl_ca_certs: Optional[str] = None,
|
|
269
271
|
ssl_ca_data: Optional[str] = None,
|
|
270
|
-
ssl_cert_reqs: str = "required",
|
|
272
|
+
ssl_cert_reqs: Union[str, VerifyMode] = "required",
|
|
271
273
|
ssl_certfile: Optional[str] = None,
|
|
272
274
|
ssl_check_hostname: bool = False,
|
|
273
275
|
ssl_keyfile: Optional[str] = None,
|
|
@@ -1633,8 +1635,9 @@ class ClusterPipeline(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterComm
|
|
|
1633
1635
|
if isinstance(result, Exception):
|
|
1634
1636
|
command = " ".join(map(safe_str, cmd.args))
|
|
1635
1637
|
msg = (
|
|
1636
|
-
f"Command # {cmd.position + 1}
|
|
1637
|
-
f"
|
|
1638
|
+
f"Command # {cmd.position + 1} "
|
|
1639
|
+
f"({truncate_text(command)}) "
|
|
1640
|
+
f"of pipeline caused error: {result.args}"
|
|
1638
1641
|
)
|
|
1639
1642
|
result.args = (msg,) + result.args[1:]
|
|
1640
1643
|
raise result
|
|
@@ -293,6 +293,9 @@ class AbstractConnection:
|
|
|
293
293
|
|
|
294
294
|
async def connect(self):
|
|
295
295
|
"""Connects to the Redis server if not already connected"""
|
|
296
|
+
await self.connect_check_health(check_health=True)
|
|
297
|
+
|
|
298
|
+
async def connect_check_health(self, check_health: bool = True):
|
|
296
299
|
if self.is_connected:
|
|
297
300
|
return
|
|
298
301
|
try:
|
|
@@ -311,7 +314,7 @@ class AbstractConnection:
|
|
|
311
314
|
try:
|
|
312
315
|
if not self.redis_connect_func:
|
|
313
316
|
# Use the default on_connect function
|
|
314
|
-
await self.
|
|
317
|
+
await self.on_connect_check_health(check_health=check_health)
|
|
315
318
|
else:
|
|
316
319
|
# Use the passed function redis_connect_func
|
|
317
320
|
(
|
|
@@ -350,6 +353,9 @@ class AbstractConnection:
|
|
|
350
353
|
|
|
351
354
|
async def on_connect(self) -> None:
|
|
352
355
|
"""Initialize the connection, authenticate and select a database"""
|
|
356
|
+
await self.on_connect_check_health(check_health=True)
|
|
357
|
+
|
|
358
|
+
async def on_connect_check_health(self, check_health: bool = True) -> None:
|
|
353
359
|
self._parser.on_connect(self)
|
|
354
360
|
parser = self._parser
|
|
355
361
|
|
|
@@ -407,7 +413,7 @@ class AbstractConnection:
|
|
|
407
413
|
# update cluster exception classes
|
|
408
414
|
self._parser.EXCEPTION_CLASSES = parser.EXCEPTION_CLASSES
|
|
409
415
|
self._parser.on_connect(self)
|
|
410
|
-
await self.send_command("HELLO", self.protocol)
|
|
416
|
+
await self.send_command("HELLO", self.protocol, check_health=check_health)
|
|
411
417
|
response = await self.read_response()
|
|
412
418
|
# if response.get(b"proto") != self.protocol and response.get(
|
|
413
419
|
# "proto"
|
|
@@ -416,18 +422,35 @@ class AbstractConnection:
|
|
|
416
422
|
|
|
417
423
|
# if a client_name is given, set it
|
|
418
424
|
if self.client_name:
|
|
419
|
-
await self.send_command(
|
|
425
|
+
await self.send_command(
|
|
426
|
+
"CLIENT",
|
|
427
|
+
"SETNAME",
|
|
428
|
+
self.client_name,
|
|
429
|
+
check_health=check_health,
|
|
430
|
+
)
|
|
420
431
|
if str_if_bytes(await self.read_response()) != "OK":
|
|
421
432
|
raise ConnectionError("Error setting client name")
|
|
422
433
|
|
|
423
434
|
# set the library name and version, pipeline for lower startup latency
|
|
424
435
|
if self.lib_name:
|
|
425
|
-
await self.send_command(
|
|
436
|
+
await self.send_command(
|
|
437
|
+
"CLIENT",
|
|
438
|
+
"SETINFO",
|
|
439
|
+
"LIB-NAME",
|
|
440
|
+
self.lib_name,
|
|
441
|
+
check_health=check_health,
|
|
442
|
+
)
|
|
426
443
|
if self.lib_version:
|
|
427
|
-
await self.send_command(
|
|
444
|
+
await self.send_command(
|
|
445
|
+
"CLIENT",
|
|
446
|
+
"SETINFO",
|
|
447
|
+
"LIB-VER",
|
|
448
|
+
self.lib_version,
|
|
449
|
+
check_health=check_health,
|
|
450
|
+
)
|
|
428
451
|
# if a database is specified, switch to it. Also pipeline this
|
|
429
452
|
if self.db:
|
|
430
|
-
await self.send_command("SELECT", self.db)
|
|
453
|
+
await self.send_command("SELECT", self.db, check_health=check_health)
|
|
431
454
|
|
|
432
455
|
# read responses from pipeline
|
|
433
456
|
for _ in (sent for sent in (self.lib_name, self.lib_version) if sent):
|
|
@@ -489,8 +512,8 @@ class AbstractConnection:
|
|
|
489
512
|
self, command: Union[bytes, str, Iterable[bytes]], check_health: bool = True
|
|
490
513
|
) -> None:
|
|
491
514
|
if not self.is_connected:
|
|
492
|
-
await self.
|
|
493
|
-
|
|
515
|
+
await self.connect_check_health(check_health=False)
|
|
516
|
+
if check_health:
|
|
494
517
|
await self.check_health()
|
|
495
518
|
|
|
496
519
|
try:
|
|
@@ -768,7 +791,7 @@ class SSLConnection(Connection):
|
|
|
768
791
|
self,
|
|
769
792
|
ssl_keyfile: Optional[str] = None,
|
|
770
793
|
ssl_certfile: Optional[str] = None,
|
|
771
|
-
ssl_cert_reqs: str = "required",
|
|
794
|
+
ssl_cert_reqs: Union[str, ssl.VerifyMode] = "required",
|
|
772
795
|
ssl_ca_certs: Optional[str] = None,
|
|
773
796
|
ssl_ca_data: Optional[str] = None,
|
|
774
797
|
ssl_check_hostname: bool = False,
|
|
@@ -842,7 +865,7 @@ class RedisSSLContext:
|
|
|
842
865
|
self,
|
|
843
866
|
keyfile: Optional[str] = None,
|
|
844
867
|
certfile: Optional[str] = None,
|
|
845
|
-
cert_reqs: Optional[str] = None,
|
|
868
|
+
cert_reqs: Optional[Union[str, ssl.VerifyMode]] = None,
|
|
846
869
|
ca_certs: Optional[str] = None,
|
|
847
870
|
ca_data: Optional[str] = None,
|
|
848
871
|
check_hostname: bool = False,
|
|
@@ -855,7 +878,7 @@ class RedisSSLContext:
|
|
|
855
878
|
self.keyfile = keyfile
|
|
856
879
|
self.certfile = certfile
|
|
857
880
|
if cert_reqs is None:
|
|
858
|
-
|
|
881
|
+
cert_reqs = ssl.CERT_NONE
|
|
859
882
|
elif isinstance(cert_reqs, str):
|
|
860
883
|
CERT_REQS = { # noqa: N806
|
|
861
884
|
"none": ssl.CERT_NONE,
|
|
@@ -866,7 +889,8 @@ class RedisSSLContext:
|
|
|
866
889
|
raise RedisError(
|
|
867
890
|
f"Invalid SSL Certificate Requirements Flag: {cert_reqs}"
|
|
868
891
|
)
|
|
869
|
-
|
|
892
|
+
cert_reqs = CERT_REQS[cert_reqs]
|
|
893
|
+
self.cert_reqs = cert_reqs
|
|
870
894
|
self.ca_certs = ca_certs
|
|
871
895
|
self.ca_data = ca_data
|
|
872
896
|
self.check_hostname = check_hostname
|
|
@@ -326,6 +326,8 @@ class Sentinel(AsyncSentinelCommands):
|
|
|
326
326
|
):
|
|
327
327
|
"""
|
|
328
328
|
Returns a redis client instance for the ``service_name`` master.
|
|
329
|
+
Sentinel client will detect failover and reconnect Redis clients
|
|
330
|
+
automatically.
|
|
329
331
|
|
|
330
332
|
A :py:class:`~redis.sentinel.SentinelConnectionPool` class is
|
|
331
333
|
used to retrieve the master's address before establishing a new
|
|
@@ -61,6 +61,7 @@ from redis.utils import (
|
|
|
61
61
|
get_lib_version,
|
|
62
62
|
safe_str,
|
|
63
63
|
str_if_bytes,
|
|
64
|
+
truncate_text,
|
|
64
65
|
)
|
|
65
66
|
|
|
66
67
|
if TYPE_CHECKING:
|
|
@@ -210,7 +211,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
|
|
|
210
211
|
ssl: bool = False,
|
|
211
212
|
ssl_keyfile: Optional[str] = None,
|
|
212
213
|
ssl_certfile: Optional[str] = None,
|
|
213
|
-
ssl_cert_reqs: str = "required",
|
|
214
|
+
ssl_cert_reqs: Union[str, "ssl.VerifyMode"] = "required",
|
|
214
215
|
ssl_ca_certs: Optional[str] = None,
|
|
215
216
|
ssl_ca_path: Optional[str] = None,
|
|
216
217
|
ssl_ca_data: Optional[str] = None,
|
|
@@ -1524,7 +1525,8 @@ class Pipeline(Redis):
|
|
|
1524
1525
|
def annotate_exception(self, exception, number, command):
|
|
1525
1526
|
cmd = " ".join(map(safe_str, command))
|
|
1526
1527
|
msg = (
|
|
1527
|
-
f"Command # {number} ({cmd}) of pipeline
|
|
1528
|
+
f"Command # {number} ({truncate_text(cmd)}) of pipeline "
|
|
1529
|
+
f"caused error: {exception.args[0]}"
|
|
1528
1530
|
)
|
|
1529
1531
|
exception.args = (msg,) + exception.args[1:]
|
|
1530
1532
|
|
|
@@ -47,6 +47,7 @@ from redis.utils import (
|
|
|
47
47
|
merge_result,
|
|
48
48
|
safe_str,
|
|
49
49
|
str_if_bytes,
|
|
50
|
+
truncate_text,
|
|
50
51
|
)
|
|
51
52
|
|
|
52
53
|
|
|
@@ -2125,7 +2126,8 @@ class ClusterPipeline(RedisCluster):
|
|
|
2125
2126
|
"""
|
|
2126
2127
|
cmd = " ".join(map(safe_str, command))
|
|
2127
2128
|
msg = (
|
|
2128
|
-
f"Command # {number} ({cmd}) of pipeline
|
|
2129
|
+
f"Command # {number} ({truncate_text(cmd)}) of pipeline "
|
|
2130
|
+
f"caused error: {exception.args[0]}"
|
|
2129
2131
|
)
|
|
2130
2132
|
exception.args = (msg,) + exception.args[1:]
|
|
2131
2133
|
|
|
@@ -6556,7 +6556,7 @@ class FunctionCommands:
|
|
|
6556
6556
|
This is a read-only variant of the FCALL command that cannot
|
|
6557
6557
|
execute commands that modify data.
|
|
6558
6558
|
|
|
6559
|
-
For more information see https://redis.io/commands/
|
|
6559
|
+
For more information see https://redis.io/commands/fcall_ro
|
|
6560
6560
|
"""
|
|
6561
6561
|
return self._fcall("FCALL_RO", function, numkeys, *keys_and_args)
|
|
6562
6562
|
|
|
@@ -72,6 +72,14 @@ class RedisModuleCommands:
|
|
|
72
72
|
tdigest = TDigestBloom(client=self)
|
|
73
73
|
return tdigest
|
|
74
74
|
|
|
75
|
+
def vset(self):
|
|
76
|
+
"""Access the VectorSet commands namespace."""
|
|
77
|
+
|
|
78
|
+
from .vectorset import VectorSet
|
|
79
|
+
|
|
80
|
+
vset = VectorSet(client=self)
|
|
81
|
+
return vset
|
|
82
|
+
|
|
75
83
|
|
|
76
84
|
class AsyncRedisModuleCommands(RedisModuleCommands):
|
|
77
85
|
def ft(self, index_name="idx"):
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from redis._parsers.helpers import pairs_to_dict
|
|
4
|
+
from redis.commands.vectorset.utils import (
|
|
5
|
+
parse_vemb_result,
|
|
6
|
+
parse_vlinks_result,
|
|
7
|
+
parse_vsim_result,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from ..helpers import get_protocol_version
|
|
11
|
+
from .commands import (
|
|
12
|
+
VEMB_CMD,
|
|
13
|
+
VGETATTR_CMD,
|
|
14
|
+
VINFO_CMD,
|
|
15
|
+
VLINKS_CMD,
|
|
16
|
+
VSIM_CMD,
|
|
17
|
+
VectorSetCommands,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class VectorSet(VectorSetCommands):
|
|
22
|
+
def __init__(self, client, **kwargs):
|
|
23
|
+
"""Create a new VectorSet client."""
|
|
24
|
+
# Set the module commands' callbacks
|
|
25
|
+
self._MODULE_CALLBACKS = {
|
|
26
|
+
VEMB_CMD: parse_vemb_result,
|
|
27
|
+
VGETATTR_CMD: lambda r: r and json.loads(r) or None,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
self._RESP2_MODULE_CALLBACKS = {
|
|
31
|
+
VINFO_CMD: lambda r: r and pairs_to_dict(r) or None,
|
|
32
|
+
VSIM_CMD: parse_vsim_result,
|
|
33
|
+
VLINKS_CMD: parse_vlinks_result,
|
|
34
|
+
}
|
|
35
|
+
self._RESP3_MODULE_CALLBACKS = {}
|
|
36
|
+
|
|
37
|
+
self.client = client
|
|
38
|
+
self.execute_command = client.execute_command
|
|
39
|
+
|
|
40
|
+
if get_protocol_version(self.client) in ["3", 3]:
|
|
41
|
+
self._MODULE_CALLBACKS.update(self._RESP3_MODULE_CALLBACKS)
|
|
42
|
+
else:
|
|
43
|
+
self._MODULE_CALLBACKS.update(self._RESP2_MODULE_CALLBACKS)
|
|
44
|
+
|
|
45
|
+
for k, v in self._MODULE_CALLBACKS.items():
|
|
46
|
+
self.client.set_response_callback(k, v)
|