redis 5.2.0__tar.gz → 5.2.1__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-5.2.0/redis.egg-info → redis-5.2.1}/PKG-INFO +1 -1
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/helpers.py +11 -4
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/connection.py +7 -1
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/sentinel.py +1 -5
- {redis-5.2.0 → redis-5.2.1/redis.egg-info}/PKG-INFO +1 -1
- {redis-5.2.0 → redis-5.2.1}/setup.py +1 -1
- {redis-5.2.0 → redis-5.2.1}/tests/conftest.py +20 -18
- redis-5.2.1/tests/ssl_utils.py +43 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_cluster.py +14 -22
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_connect.py +16 -13
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_cwe_404.py +2 -2
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_graph.py +20 -20
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_hash.py +7 -6
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_search.py +2 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_sentinel.py +20 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_timeseries.py +5 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_cluster.py +7 -6
- {redis-5.2.0 → redis-5.2.1}/tests/test_connect.py +14 -13
- {redis-5.2.0 → redis-5.2.1}/tests/test_graph.py +23 -23
- {redis-5.2.0 → redis-5.2.1}/tests/test_graph_utils/test_edge.py +4 -4
- {redis-5.2.0 → redis-5.2.1}/tests/test_graph_utils/test_node.py +3 -3
- {redis-5.2.0 → redis-5.2.1}/tests/test_graph_utils/test_path.py +5 -5
- {redis-5.2.0 → redis-5.2.1}/tests/test_hash.py +7 -6
- {redis-5.2.0 → redis-5.2.1}/tests/test_json.py +2 -2
- {redis-5.2.0 → redis-5.2.1}/tests/test_search.py +13 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_ssl.py +29 -26
- redis-5.2.0/tests/ssl_utils.py +0 -14
- {redis-5.2.0 → redis-5.2.1}/INSTALL +0 -0
- {redis-5.2.0 → redis-5.2.1}/LICENSE +0 -0
- {redis-5.2.0 → redis-5.2.1}/MANIFEST.in +0 -0
- {redis-5.2.0 → redis-5.2.1}/README.md +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/base.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/encoders.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/hiredis.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/resp2.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/resp3.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/_parsers/socket.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/client.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/cluster.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/lock.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/retry.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/asyncio/utils.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/backoff.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/cache.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/client.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/cluster.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/bf/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/bf/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/bf/info.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/cluster.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/core.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/edge.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/exceptions.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/execution_plan.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/node.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/path.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/graph/query_result.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/helpers.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/json/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/json/_util.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/json/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/json/decoders.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/json/path.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/redismodules.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/_util.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/aggregation.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/document.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/field.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/indexDefinition.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/query.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/querystring.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/reducers.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/result.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/search/suggestion.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/sentinel.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/timeseries/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/timeseries/commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/timeseries/info.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/commands/timeseries/utils.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/connection.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/crc.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/credentials.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/exceptions.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/lock.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/ocsp.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/retry.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/sentinel.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/typing.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis/utils.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis.egg-info/SOURCES.txt +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis.egg-info/dependency_links.txt +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis.egg-info/requires.txt +0 -0
- {redis-5.2.0 → redis-5.2.1}/redis.egg-info/top_level.txt +0 -0
- {redis-5.2.0 → redis-5.2.1}/setup.cfg +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/mocks.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/compat.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/conftest.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/mocks.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_bloom.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_connection.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_connection_pool.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_credentials.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_encoding.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_json.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_lock.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_monitor.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_pipeline.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_pubsub.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_retry.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_scripting.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/test_sentinel_managed_connection.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/testdata/jsontestdata.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/testdata/titles.csv +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_asyncio/testdata/will_play_text.csv.bz2 +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_bloom.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_cache.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_command_parser.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_commands.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_connection.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_connection_pool.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_credentials.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_encoding.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_function.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_graph_utils/__init__.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_helpers.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_lock.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_monitor.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_multiprocessing.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_parsers/test_helpers.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_pipeline.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_pubsub.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_retry.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_scripting.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_sentinel.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_timeseries.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/test_utils.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/testdata/jsontestdata.py +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/testdata/titles.csv +0 -0
- {redis-5.2.0 → redis-5.2.1}/tests/testdata/will_play_text.csv.bz2 +0 -0
|
@@ -396,13 +396,20 @@ def parse_slowlog_get(response, **options):
|
|
|
396
396
|
# an O(N) complexity) instead of the command.
|
|
397
397
|
if isinstance(item[3], list):
|
|
398
398
|
result["command"] = space.join(item[3])
|
|
399
|
-
|
|
400
|
-
|
|
399
|
+
|
|
400
|
+
# These fields are optional, depends on environment.
|
|
401
|
+
if len(item) >= 6:
|
|
402
|
+
result["client_address"] = item[4]
|
|
403
|
+
result["client_name"] = item[5]
|
|
401
404
|
else:
|
|
402
405
|
result["complexity"] = item[3]
|
|
403
406
|
result["command"] = space.join(item[4])
|
|
404
|
-
|
|
405
|
-
|
|
407
|
+
|
|
408
|
+
# These fields are optional, depends on environment.
|
|
409
|
+
if len(item) >= 7:
|
|
410
|
+
result["client_address"] = item[5]
|
|
411
|
+
result["client_name"] = item[6]
|
|
412
|
+
|
|
406
413
|
return result
|
|
407
414
|
|
|
408
415
|
return [parse_item(item) for item in response]
|
|
@@ -214,7 +214,13 @@ class AbstractConnection:
|
|
|
214
214
|
_warnings.warn(
|
|
215
215
|
f"unclosed Connection {self!r}", ResourceWarning, source=self
|
|
216
216
|
)
|
|
217
|
-
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
asyncio.get_running_loop()
|
|
220
|
+
self._close()
|
|
221
|
+
except RuntimeError:
|
|
222
|
+
# No actions been taken if pool already closed.
|
|
223
|
+
pass
|
|
218
224
|
|
|
219
225
|
def _close(self):
|
|
220
226
|
"""
|
|
@@ -29,11 +29,7 @@ class SentinelManagedConnection(Connection):
|
|
|
29
29
|
super().__init__(**kwargs)
|
|
30
30
|
|
|
31
31
|
def __repr__(self):
|
|
32
|
-
|
|
33
|
-
s = (
|
|
34
|
-
f"<{self.__class__.__module__}.{self.__class__.__name__}"
|
|
35
|
-
f"(service={pool.service_name}"
|
|
36
|
-
)
|
|
32
|
+
s = f"<{self.__class__.__module__}.{self.__class__.__name__}"
|
|
37
33
|
if self.host:
|
|
38
34
|
host_info = f",host={self.host},port={self.port}"
|
|
39
35
|
s += host_info
|
|
@@ -21,7 +21,7 @@ from redis.cache import (
|
|
|
21
21
|
from redis.connection import Connection, ConnectionInterface, SSLConnection, parse_url
|
|
22
22
|
from redis.exceptions import RedisClusterException
|
|
23
23
|
from redis.retry import Retry
|
|
24
|
-
from tests.ssl_utils import
|
|
24
|
+
from tests.ssl_utils import get_tls_certificates
|
|
25
25
|
|
|
26
26
|
REDIS_INFO = {}
|
|
27
27
|
default_redis_url = "redis://localhost:6379/0"
|
|
@@ -103,6 +103,13 @@ def pytest_addoption(parser):
|
|
|
103
103
|
help="Redis connection string, defaults to `%(default)s`",
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
+
parser.addoption(
|
|
107
|
+
"--redis-mod-url",
|
|
108
|
+
default=default_redismod_url,
|
|
109
|
+
action="store",
|
|
110
|
+
help="Redis with modules connection string, defaults to `%(default)s`",
|
|
111
|
+
)
|
|
112
|
+
|
|
106
113
|
parser.addoption(
|
|
107
114
|
"--protocol",
|
|
108
115
|
default=default_protocol,
|
|
@@ -177,14 +184,14 @@ def pytest_sessionstart(session):
|
|
|
177
184
|
REDIS_INFO["version"] = version
|
|
178
185
|
REDIS_INFO["arch_bits"] = arch_bits
|
|
179
186
|
REDIS_INFO["cluster_enabled"] = cluster_enabled
|
|
187
|
+
REDIS_INFO["tls_cert_subdir"] = "cluster" if cluster_enabled else "standalone"
|
|
180
188
|
REDIS_INFO["enterprise"] = enterprise
|
|
181
189
|
# store REDIS_INFO in config so that it is available from "condition strings"
|
|
182
190
|
session.config.REDIS_INFO = REDIS_INFO
|
|
183
191
|
|
|
184
192
|
# module info
|
|
185
|
-
stack_url =
|
|
186
|
-
|
|
187
|
-
stack_url = default_redismod_url
|
|
193
|
+
stack_url = session.config.getoption("--redis-mod-url")
|
|
194
|
+
|
|
188
195
|
try:
|
|
189
196
|
stack_info = _get_info(stack_url)
|
|
190
197
|
REDIS_INFO["modules"] = stack_info["modules"]
|
|
@@ -325,6 +332,9 @@ def _get_client(
|
|
|
325
332
|
redis_url = request.config.getoption("--redis-url")
|
|
326
333
|
else:
|
|
327
334
|
redis_url = from_url
|
|
335
|
+
|
|
336
|
+
redis_tls_url = request.config.getoption("--redis-ssl-url")
|
|
337
|
+
|
|
328
338
|
if "protocol" not in redis_url and kwargs.get("protocol") is None:
|
|
329
339
|
kwargs["protocol"] = request.config.getoption("--protocol")
|
|
330
340
|
|
|
@@ -335,15 +345,11 @@ def _get_client(
|
|
|
335
345
|
connection_class = Connection
|
|
336
346
|
if ssl:
|
|
337
347
|
connection_class = SSLConnection
|
|
338
|
-
kwargs["ssl_certfile"] =
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
# I can't explain how does it work -_-
|
|
344
|
-
kwargs["ssl_cert_reqs"] = "require" + "d"
|
|
345
|
-
kwargs["ssl_ca_certs"] = get_ssl_filename("ca-cert.pem")
|
|
346
|
-
kwargs["port"] = 6666
|
|
348
|
+
kwargs["ssl_certfile"], kwargs["ssl_keyfile"], kwargs["ssl_ca_certs"] = (
|
|
349
|
+
get_tls_certificates()
|
|
350
|
+
)
|
|
351
|
+
kwargs["ssl_cert_reqs"] = "required"
|
|
352
|
+
kwargs["port"] = urlparse(redis_tls_url).port
|
|
347
353
|
kwargs["connection_class"] = connection_class
|
|
348
354
|
url_options.update(kwargs)
|
|
349
355
|
pool = redis.ConnectionPool(**url_options)
|
|
@@ -393,11 +399,7 @@ def r(request):
|
|
|
393
399
|
|
|
394
400
|
@pytest.fixture()
|
|
395
401
|
def stack_url(request):
|
|
396
|
-
|
|
397
|
-
if stack_url == default_redis_url:
|
|
398
|
-
return default_redismod_url
|
|
399
|
-
else:
|
|
400
|
-
return stack_url
|
|
402
|
+
return request.config.getoption("--redis-mod-url", default=default_redismod_url)
|
|
401
403
|
|
|
402
404
|
|
|
403
405
|
@pytest.fixture()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
import os
|
|
3
|
+
from collections import namedtuple
|
|
4
|
+
|
|
5
|
+
CLIENT_CERT_NAME = "client.crt"
|
|
6
|
+
CLIENT_KEY_NAME = "client.key"
|
|
7
|
+
SERVER_CERT_NAME = "redis.crt"
|
|
8
|
+
SERVER_KEY_NAME = "redis.key"
|
|
9
|
+
CA_CERT_NAME = "ca.crt"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class CertificateType(str, enum.Enum):
|
|
13
|
+
client = "client"
|
|
14
|
+
server = "server"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
TLSFiles = namedtuple("TLSFiles", ["certfile", "keyfile", "ca_certfile"])
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_tls_certificates(
|
|
21
|
+
subdir: str = "standalone",
|
|
22
|
+
cert_type: CertificateType = CertificateType.client,
|
|
23
|
+
):
|
|
24
|
+
root = os.path.join(os.path.dirname(__file__), "..")
|
|
25
|
+
cert_subdir = ("dockers", subdir, "tls")
|
|
26
|
+
cert_dir = os.path.abspath(os.path.join(root, *cert_subdir))
|
|
27
|
+
if not os.path.isdir(cert_dir): # github actions package validation case
|
|
28
|
+
cert_dir = os.path.abspath(os.path.join(root, "..", *cert_subdir))
|
|
29
|
+
if not os.path.isdir(cert_dir):
|
|
30
|
+
raise OSError(f"No SSL certificates found. They should be in {cert_dir}")
|
|
31
|
+
|
|
32
|
+
if cert_type == CertificateType.client:
|
|
33
|
+
return TLSFiles(
|
|
34
|
+
os.path.join(cert_dir, CLIENT_CERT_NAME),
|
|
35
|
+
os.path.join(cert_dir, CLIENT_KEY_NAME),
|
|
36
|
+
os.path.join(cert_dir, CA_CERT_NAME),
|
|
37
|
+
)
|
|
38
|
+
elif cert_type == CertificateType.server:
|
|
39
|
+
return TLSFiles(
|
|
40
|
+
os.path.join(cert_dir, SERVER_CERT_NAME),
|
|
41
|
+
os.path.join(cert_dir, SERVER_KEY_NAME),
|
|
42
|
+
os.path.join(cert_dir, CA_CERT_NAME),
|
|
43
|
+
)
|
|
@@ -33,12 +33,11 @@ from tests.conftest import (
|
|
|
33
33
|
assert_resp_response,
|
|
34
34
|
is_resp2_connection,
|
|
35
35
|
skip_if_redis_enterprise,
|
|
36
|
-
skip_if_server_version_gte,
|
|
37
36
|
skip_if_server_version_lt,
|
|
38
37
|
skip_unless_arch_bits,
|
|
39
38
|
)
|
|
40
39
|
|
|
41
|
-
from ..ssl_utils import
|
|
40
|
+
from ..ssl_utils import get_tls_certificates
|
|
42
41
|
from .compat import aclosing, mock
|
|
43
42
|
|
|
44
43
|
pytestmark = pytest.mark.onlycluster
|
|
@@ -380,20 +379,22 @@ class TestRedisClusterObj:
|
|
|
380
379
|
async with RedisCluster.from_url(url) as rc_default:
|
|
381
380
|
# Test default retry
|
|
382
381
|
retry = rc_default.connection_kwargs.get("retry")
|
|
382
|
+
|
|
383
|
+
# FIXME: Workaround for https://github.com/redis/redis-py/issues/3030
|
|
384
|
+
host = rc_default.get_default_node().host
|
|
385
|
+
|
|
383
386
|
assert isinstance(retry, Retry)
|
|
384
387
|
assert retry._retries == 3
|
|
385
388
|
assert isinstance(retry._backoff, type(default_backoff()))
|
|
386
|
-
assert rc_default.get_node(
|
|
389
|
+
assert rc_default.get_node(host, 16379).connection_kwargs.get(
|
|
387
390
|
"retry"
|
|
388
|
-
) == rc_default.get_node(
|
|
391
|
+
) == rc_default.get_node(host, 16380).connection_kwargs.get("retry")
|
|
389
392
|
|
|
390
393
|
retry = Retry(ExponentialBackoff(10, 5), 5)
|
|
391
394
|
async with RedisCluster.from_url(url, retry=retry) as rc_custom_retry:
|
|
392
395
|
# Test custom retry
|
|
393
396
|
assert (
|
|
394
|
-
rc_custom_retry.get_node(
|
|
395
|
-
"retry"
|
|
396
|
-
)
|
|
397
|
+
rc_custom_retry.get_node(host, 16379).connection_kwargs.get("retry")
|
|
397
398
|
== retry
|
|
398
399
|
)
|
|
399
400
|
|
|
@@ -402,9 +403,7 @@ class TestRedisClusterObj:
|
|
|
402
403
|
) as rc_no_retries:
|
|
403
404
|
# Test no connection retries
|
|
404
405
|
assert (
|
|
405
|
-
rc_no_retries.get_node(
|
|
406
|
-
"retry"
|
|
407
|
-
)
|
|
406
|
+
rc_no_retries.get_node(host, 16379).connection_kwargs.get("retry")
|
|
408
407
|
is None
|
|
409
408
|
)
|
|
410
409
|
|
|
@@ -412,7 +411,7 @@ class TestRedisClusterObj:
|
|
|
412
411
|
url, retry=Retry(NoBackoff(), 0)
|
|
413
412
|
) as rc_no_retries:
|
|
414
413
|
assert (
|
|
415
|
-
rc_no_retries.get_node(
|
|
414
|
+
rc_no_retries.get_node(host, 16379)
|
|
416
415
|
.connection_kwargs.get("retry")
|
|
417
416
|
._retries
|
|
418
417
|
== 0
|
|
@@ -493,8 +492,8 @@ class TestRedisClusterObj:
|
|
|
493
492
|
Test command execution with nodes flag REPLICAS
|
|
494
493
|
"""
|
|
495
494
|
replicas = r.get_replicas()
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
assert len(replicas) != 0, "This test requires Cluster with 1 replica"
|
|
496
|
+
|
|
498
497
|
primaries = r.get_primaries()
|
|
499
498
|
mock_all_nodes_resp(r, "PONG")
|
|
500
499
|
assert await r.ping(target_nodes=RedisCluster.REPLICAS) is True
|
|
@@ -2804,7 +2803,6 @@ class TestClusterPipeline:
|
|
|
2804
2803
|
assert ask_node._free.pop().read_response.await_count
|
|
2805
2804
|
assert res == ["MOCK_OK"]
|
|
2806
2805
|
|
|
2807
|
-
@skip_if_server_version_gte("7.0.0")
|
|
2808
2806
|
async def test_moved_redirection_on_slave_with_default(
|
|
2809
2807
|
self, r: RedisCluster
|
|
2810
2808
|
) -> None:
|
|
@@ -2824,11 +2822,7 @@ class TestClusterPipeline:
|
|
|
2824
2822
|
async def parse_response(
|
|
2825
2823
|
self, connection: Connection, command: str, **kwargs: Any
|
|
2826
2824
|
) -> Any:
|
|
2827
|
-
if
|
|
2828
|
-
command == "GET"
|
|
2829
|
-
and self.host != primary.host
|
|
2830
|
-
and self.port != primary.port
|
|
2831
|
-
):
|
|
2825
|
+
if command == "GET" and self.port != primary.port:
|
|
2832
2826
|
raise MovedError(moved_error)
|
|
2833
2827
|
|
|
2834
2828
|
return await parse_response_orig(connection, command, **kwargs)
|
|
@@ -2899,9 +2893,7 @@ class TestSSL:
|
|
|
2899
2893
|
appropriate port.
|
|
2900
2894
|
"""
|
|
2901
2895
|
|
|
2902
|
-
CA_CERT =
|
|
2903
|
-
CLIENT_CERT = get_ssl_filename("client-cert.pem")
|
|
2904
|
-
CLIENT_KEY = get_ssl_filename("client-key.pem")
|
|
2896
|
+
CLIENT_CERT, CLIENT_KEY, CA_CERT = get_tls_certificates("cluster")
|
|
2905
2897
|
|
|
2906
2898
|
@pytest_asyncio.fixture()
|
|
2907
2899
|
def create_client(self, request: FixtureRequest) -> Callable[..., RedisCluster]:
|
|
@@ -11,7 +11,7 @@ from redis.asyncio.connection import (
|
|
|
11
11
|
)
|
|
12
12
|
from redis.exceptions import ConnectionError
|
|
13
13
|
|
|
14
|
-
from ..ssl_utils import
|
|
14
|
+
from ..ssl_utils import CertificateType, get_tls_certificates
|
|
15
15
|
|
|
16
16
|
_CLIENT_NAME = "test-suite-client"
|
|
17
17
|
_CMD_SEP = b"\r\n"
|
|
@@ -57,19 +57,21 @@ async def test_uds_connect(uds_address):
|
|
|
57
57
|
)
|
|
58
58
|
async def test_tcp_ssl_tls12_custom_ciphers(tcp_address, ssl_ciphers):
|
|
59
59
|
host, port = tcp_address
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
|
|
61
|
+
server_certs = get_tls_certificates(cert_type=CertificateType.server)
|
|
62
|
+
|
|
63
63
|
conn = SSLConnection(
|
|
64
64
|
host=host,
|
|
65
65
|
port=port,
|
|
66
66
|
client_name=_CLIENT_NAME,
|
|
67
|
-
ssl_ca_certs=ca_certfile,
|
|
67
|
+
ssl_ca_certs=server_certs.ca_certfile,
|
|
68
68
|
socket_timeout=10,
|
|
69
69
|
ssl_min_version=ssl.TLSVersion.TLSv1_2,
|
|
70
70
|
ssl_ciphers=ssl_ciphers,
|
|
71
71
|
)
|
|
72
|
-
await _assert_connect(
|
|
72
|
+
await _assert_connect(
|
|
73
|
+
conn, tcp_address, certfile=server_certs.certfile, keyfile=server_certs.keyfile
|
|
74
|
+
)
|
|
73
75
|
await conn.disconnect()
|
|
74
76
|
|
|
75
77
|
|
|
@@ -86,18 +88,20 @@ async def test_tcp_ssl_tls12_custom_ciphers(tcp_address, ssl_ciphers):
|
|
|
86
88
|
)
|
|
87
89
|
async def test_tcp_ssl_connect(tcp_address, ssl_min_version):
|
|
88
90
|
host, port = tcp_address
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
|
|
92
|
+
server_certs = get_tls_certificates(cert_type=CertificateType.server)
|
|
93
|
+
|
|
92
94
|
conn = SSLConnection(
|
|
93
95
|
host=host,
|
|
94
96
|
port=port,
|
|
95
97
|
client_name=_CLIENT_NAME,
|
|
96
|
-
ssl_ca_certs=ca_certfile,
|
|
98
|
+
ssl_ca_certs=server_certs.ca_certfile,
|
|
97
99
|
socket_timeout=10,
|
|
98
100
|
ssl_min_version=ssl_min_version,
|
|
99
101
|
)
|
|
100
|
-
await _assert_connect(
|
|
102
|
+
await _assert_connect(
|
|
103
|
+
conn, tcp_address, certfile=server_certs.certfile, keyfile=server_certs.keyfile
|
|
104
|
+
)
|
|
101
105
|
await conn.disconnect()
|
|
102
106
|
|
|
103
107
|
|
|
@@ -105,8 +109,7 @@ async def test_tcp_ssl_connect(tcp_address, ssl_min_version):
|
|
|
105
109
|
@pytest.mark.skipif(not ssl.HAS_TLSv1_3, reason="requires TLSv1.3")
|
|
106
110
|
async def test_tcp_ssl_version_mismatch(tcp_address):
|
|
107
111
|
host, port = tcp_address
|
|
108
|
-
certfile =
|
|
109
|
-
keyfile = get_ssl_filename("server-key.pem")
|
|
112
|
+
certfile, keyfile, _ = get_tls_certificates(cert_type=CertificateType.server)
|
|
110
113
|
conn = SSLConnection(
|
|
111
114
|
host=host,
|
|
112
115
|
port=port,
|
|
@@ -208,7 +208,7 @@ async def test_cluster(master_host):
|
|
|
208
208
|
port = cluster_port + i
|
|
209
209
|
remapped = remap_base + i
|
|
210
210
|
forward_addr = hostname, port
|
|
211
|
-
proxy = DelayProxy(addr=(
|
|
211
|
+
proxy = DelayProxy(addr=(hostname, remapped), redis_addr=forward_addr)
|
|
212
212
|
proxies.append(proxy)
|
|
213
213
|
|
|
214
214
|
def all_clear():
|
|
@@ -233,7 +233,7 @@ async def test_cluster(master_host):
|
|
|
233
233
|
await stack.enter_async_context(p)
|
|
234
234
|
|
|
235
235
|
r = RedisCluster.from_url(
|
|
236
|
-
f"redis://
|
|
236
|
+
f"redis://{hostname}:{remap_base}", address_remap=remap
|
|
237
237
|
)
|
|
238
238
|
try:
|
|
239
239
|
await r.initialize()
|
|
@@ -12,7 +12,7 @@ async def decoded_r(create_redis, stack_url):
|
|
|
12
12
|
return await create_redis(decode_responses=True, url="redis://localhost:6480")
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
@pytest.mark.
|
|
15
|
+
@pytest.mark.graph
|
|
16
16
|
@skip_if_resp_version(3)
|
|
17
17
|
async def test_bulk(decoded_r):
|
|
18
18
|
with pytest.raises(NotImplementedError):
|
|
@@ -20,7 +20,7 @@ async def test_bulk(decoded_r):
|
|
|
20
20
|
await decoded_r.graph().bulk(foo="bar!")
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
@pytest.mark.
|
|
23
|
+
@pytest.mark.graph
|
|
24
24
|
@skip_if_resp_version(3)
|
|
25
25
|
async def test_graph_creation(decoded_r: redis.Redis):
|
|
26
26
|
graph = decoded_r.graph()
|
|
@@ -66,7 +66,7 @@ async def test_graph_creation(decoded_r: redis.Redis):
|
|
|
66
66
|
await graph.delete()
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
@pytest.mark.
|
|
69
|
+
@pytest.mark.graph
|
|
70
70
|
@skip_if_resp_version(3)
|
|
71
71
|
async def test_array_functions(decoded_r: redis.Redis):
|
|
72
72
|
graph = decoded_r.graph()
|
|
@@ -90,7 +90,7 @@ async def test_array_functions(decoded_r: redis.Redis):
|
|
|
90
90
|
assert [a] == result.result_set[0][0]
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
@pytest.mark.
|
|
93
|
+
@pytest.mark.graph
|
|
94
94
|
@skip_if_resp_version(3)
|
|
95
95
|
async def test_path(decoded_r: redis.Redis):
|
|
96
96
|
node0 = Node(node_id=0, label="L1")
|
|
@@ -111,7 +111,7 @@ async def test_path(decoded_r: redis.Redis):
|
|
|
111
111
|
assert expected_results == result.result_set
|
|
112
112
|
|
|
113
113
|
|
|
114
|
-
@pytest.mark.
|
|
114
|
+
@pytest.mark.graph
|
|
115
115
|
@skip_if_resp_version(3)
|
|
116
116
|
async def test_param(decoded_r: redis.Redis):
|
|
117
117
|
params = [1, 2.3, "str", True, False, None, [0, 1, 2]]
|
|
@@ -122,7 +122,7 @@ async def test_param(decoded_r: redis.Redis):
|
|
|
122
122
|
assert expected_results == result.result_set
|
|
123
123
|
|
|
124
124
|
|
|
125
|
-
@pytest.mark.
|
|
125
|
+
@pytest.mark.graph
|
|
126
126
|
@skip_if_resp_version(3)
|
|
127
127
|
async def test_map(decoded_r: redis.Redis):
|
|
128
128
|
query = "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"
|
|
@@ -140,7 +140,7 @@ async def test_map(decoded_r: redis.Redis):
|
|
|
140
140
|
assert actual == expected
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
@pytest.mark.
|
|
143
|
+
@pytest.mark.graph
|
|
144
144
|
@skip_if_resp_version(3)
|
|
145
145
|
async def test_point(decoded_r: redis.Redis):
|
|
146
146
|
query = "RETURN point({latitude: 32.070794860, longitude: 34.820751118})"
|
|
@@ -158,7 +158,7 @@ async def test_point(decoded_r: redis.Redis):
|
|
|
158
158
|
assert abs(actual["longitude"] - expected_lon) < 0.001
|
|
159
159
|
|
|
160
160
|
|
|
161
|
-
@pytest.mark.
|
|
161
|
+
@pytest.mark.graph
|
|
162
162
|
@skip_if_resp_version(3)
|
|
163
163
|
async def test_index_response(decoded_r: redis.Redis):
|
|
164
164
|
result_set = await decoded_r.graph().query("CREATE INDEX ON :person(age)")
|
|
@@ -174,7 +174,7 @@ async def test_index_response(decoded_r: redis.Redis):
|
|
|
174
174
|
await decoded_r.graph().query("DROP INDEX ON :person(age)")
|
|
175
175
|
|
|
176
176
|
|
|
177
|
-
@pytest.mark.
|
|
177
|
+
@pytest.mark.graph
|
|
178
178
|
@skip_if_resp_version(3)
|
|
179
179
|
async def test_stringify_query_result(decoded_r: redis.Redis):
|
|
180
180
|
graph = decoded_r.graph()
|
|
@@ -229,7 +229,7 @@ async def test_stringify_query_result(decoded_r: redis.Redis):
|
|
|
229
229
|
await graph.delete()
|
|
230
230
|
|
|
231
231
|
|
|
232
|
-
@pytest.mark.
|
|
232
|
+
@pytest.mark.graph
|
|
233
233
|
@skip_if_resp_version(3)
|
|
234
234
|
async def test_optional_match(decoded_r: redis.Redis):
|
|
235
235
|
# Build a graph of form (a)-[R]->(b)
|
|
@@ -255,7 +255,7 @@ async def test_optional_match(decoded_r: redis.Redis):
|
|
|
255
255
|
await graph.delete()
|
|
256
256
|
|
|
257
257
|
|
|
258
|
-
@pytest.mark.
|
|
258
|
+
@pytest.mark.graph
|
|
259
259
|
@skip_if_resp_version(3)
|
|
260
260
|
async def test_cached_execution(decoded_r: redis.Redis):
|
|
261
261
|
await decoded_r.graph().query("CREATE ()")
|
|
@@ -276,7 +276,7 @@ async def test_cached_execution(decoded_r: redis.Redis):
|
|
|
276
276
|
assert cached_result.cached_execution
|
|
277
277
|
|
|
278
278
|
|
|
279
|
-
@pytest.mark.
|
|
279
|
+
@pytest.mark.graph
|
|
280
280
|
@skip_if_resp_version(3)
|
|
281
281
|
async def test_slowlog(decoded_r: redis.Redis):
|
|
282
282
|
create_query = """CREATE
|
|
@@ -291,7 +291,7 @@ async def test_slowlog(decoded_r: redis.Redis):
|
|
|
291
291
|
|
|
292
292
|
|
|
293
293
|
@pytest.mark.xfail(strict=False)
|
|
294
|
-
@pytest.mark.
|
|
294
|
+
@pytest.mark.graph
|
|
295
295
|
@skip_if_resp_version(3)
|
|
296
296
|
async def test_query_timeout(decoded_r: redis.Redis):
|
|
297
297
|
# Build a sample graph with 1000 nodes.
|
|
@@ -306,7 +306,7 @@ async def test_query_timeout(decoded_r: redis.Redis):
|
|
|
306
306
|
assert False is False
|
|
307
307
|
|
|
308
308
|
|
|
309
|
-
@pytest.mark.
|
|
309
|
+
@pytest.mark.graph
|
|
310
310
|
@skip_if_resp_version(3)
|
|
311
311
|
async def test_read_only_query(decoded_r: redis.Redis):
|
|
312
312
|
with pytest.raises(Exception):
|
|
@@ -316,7 +316,7 @@ async def test_read_only_query(decoded_r: redis.Redis):
|
|
|
316
316
|
assert False is False
|
|
317
317
|
|
|
318
318
|
|
|
319
|
-
@pytest.mark.
|
|
319
|
+
@pytest.mark.graph
|
|
320
320
|
@skip_if_resp_version(3)
|
|
321
321
|
async def test_profile(decoded_r: redis.Redis):
|
|
322
322
|
q = """UNWIND range(1, 3) AS x CREATE (p:Person {v:x})"""
|
|
@@ -333,7 +333,7 @@ async def test_profile(decoded_r: redis.Redis):
|
|
|
333
333
|
|
|
334
334
|
|
|
335
335
|
@skip_if_redis_enterprise()
|
|
336
|
-
@pytest.mark.
|
|
336
|
+
@pytest.mark.graph
|
|
337
337
|
@skip_if_resp_version(3)
|
|
338
338
|
async def test_config(decoded_r: redis.Redis):
|
|
339
339
|
config_name = "RESULTSET_SIZE"
|
|
@@ -366,7 +366,7 @@ async def test_config(decoded_r: redis.Redis):
|
|
|
366
366
|
|
|
367
367
|
|
|
368
368
|
@pytest.mark.onlynoncluster
|
|
369
|
-
@pytest.mark.
|
|
369
|
+
@pytest.mark.graph
|
|
370
370
|
@skip_if_resp_version(3)
|
|
371
371
|
async def test_list_keys(decoded_r: redis.Redis):
|
|
372
372
|
result = await decoded_r.graph().list_keys()
|
|
@@ -390,7 +390,7 @@ async def test_list_keys(decoded_r: redis.Redis):
|
|
|
390
390
|
assert result == []
|
|
391
391
|
|
|
392
392
|
|
|
393
|
-
@pytest.mark.
|
|
393
|
+
@pytest.mark.graph
|
|
394
394
|
@skip_if_resp_version(3)
|
|
395
395
|
async def test_multi_label(decoded_r: redis.Redis):
|
|
396
396
|
redis_graph = decoded_r.graph("g")
|
|
@@ -417,7 +417,7 @@ async def test_multi_label(decoded_r: redis.Redis):
|
|
|
417
417
|
assert True
|
|
418
418
|
|
|
419
419
|
|
|
420
|
-
@pytest.mark.
|
|
420
|
+
@pytest.mark.graph
|
|
421
421
|
@skip_if_resp_version(3)
|
|
422
422
|
async def test_execution_plan(decoded_r: redis.Redis):
|
|
423
423
|
redis_graph = decoded_r.graph("execution_plan")
|
|
@@ -437,7 +437,7 @@ async def test_execution_plan(decoded_r: redis.Redis):
|
|
|
437
437
|
await redis_graph.delete()
|
|
438
438
|
|
|
439
439
|
|
|
440
|
-
@pytest.mark.
|
|
440
|
+
@pytest.mark.graph
|
|
441
441
|
@skip_if_resp_version(3)
|
|
442
442
|
async def test_explain(decoded_r: redis.Redis):
|
|
443
443
|
redis_graph = decoded_r.graph("execution_plan")
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import math
|
|
2
3
|
from datetime import datetime, timedelta
|
|
3
4
|
|
|
4
5
|
from tests.conftest import skip_if_server_version_lt
|
|
@@ -128,9 +129,9 @@ async def test_hpexpire_multiple_fields(r):
|
|
|
128
129
|
async def test_hexpireat_basic(r):
|
|
129
130
|
await r.delete("test:hash")
|
|
130
131
|
await r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
|
|
131
|
-
exp_time =
|
|
132
|
+
exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
|
|
132
133
|
assert await r.hexpireat("test:hash", exp_time, "field1") == [1]
|
|
133
|
-
await asyncio.sleep(
|
|
134
|
+
await asyncio.sleep(2.1)
|
|
134
135
|
assert await r.hexists("test:hash", "field1") is False
|
|
135
136
|
assert await r.hexists("test:hash", "field2") is True
|
|
136
137
|
|
|
@@ -139,9 +140,9 @@ async def test_hexpireat_basic(r):
|
|
|
139
140
|
async def test_hexpireat_with_datetime(r):
|
|
140
141
|
await r.delete("test:hash")
|
|
141
142
|
await r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
|
|
142
|
-
exp_time = datetime.now() + timedelta(seconds=
|
|
143
|
+
exp_time = (datetime.now() + timedelta(seconds=2)).replace(microsecond=0)
|
|
143
144
|
assert await r.hexpireat("test:hash", exp_time, "field1") == [1]
|
|
144
|
-
await asyncio.sleep(
|
|
145
|
+
await asyncio.sleep(2.1)
|
|
145
146
|
assert await r.hexists("test:hash", "field1") is False
|
|
146
147
|
assert await r.hexists("test:hash", "field2") is True
|
|
147
148
|
|
|
@@ -175,9 +176,9 @@ async def test_hexpireat_multiple_fields(r):
|
|
|
175
176
|
"test:hash",
|
|
176
177
|
mapping={"field1": "value1", "field2": "value2", "field3": "value3"},
|
|
177
178
|
)
|
|
178
|
-
exp_time =
|
|
179
|
+
exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
|
|
179
180
|
assert await r.hexpireat("test:hash", exp_time, "field1", "field2") == [1, 1]
|
|
180
|
-
await asyncio.sleep(1
|
|
181
|
+
await asyncio.sleep(2.1)
|
|
181
182
|
assert await r.hexists("test:hash", "field1") is False
|
|
182
183
|
assert await r.hexists("test:hash", "field2") is False
|
|
183
184
|
assert await r.hexists("test:hash", "field3") is True
|
|
@@ -1025,6 +1025,8 @@ async def test_phonetic_matcher(decoded_r: redis.Redis):
|
|
|
1025
1025
|
|
|
1026
1026
|
@pytest.mark.redismod
|
|
1027
1027
|
@pytest.mark.onlynoncluster
|
|
1028
|
+
# NOTE(imalinovskyi): This test contains hardcoded scores valid only for RediSearch 2.8+
|
|
1029
|
+
@skip_ifmodversion_lt("2.8.0", "search")
|
|
1028
1030
|
async def test_scorer(decoded_r: redis.Redis):
|
|
1029
1031
|
await decoded_r.ft().create_index((TextField("description"),))
|
|
1030
1032
|
|
|
@@ -264,3 +264,23 @@ async def test_auto_close_pool(cluster, sentinel, method_name):
|
|
|
264
264
|
|
|
265
265
|
assert calls == 1
|
|
266
266
|
await pool.disconnect()
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@pytest.mark.onlynoncluster
|
|
270
|
+
async def test_repr_correctly_represents_connection_object(sentinel):
|
|
271
|
+
pool = SentinelConnectionPool("mymaster", sentinel)
|
|
272
|
+
connection = await pool.get_connection("PING")
|
|
273
|
+
|
|
274
|
+
assert (
|
|
275
|
+
str(connection)
|
|
276
|
+
== "<redis.asyncio.sentinel.SentinelManagedConnection,host=127.0.0.1,port=6379)>" # noqa: E501
|
|
277
|
+
)
|
|
278
|
+
assert connection.connection_pool == pool
|
|
279
|
+
await pool.release(connection)
|
|
280
|
+
|
|
281
|
+
del pool
|
|
282
|
+
|
|
283
|
+
assert (
|
|
284
|
+
str(connection)
|
|
285
|
+
== "<redis.asyncio.sentinel.SentinelManagedConnection,host=127.0.0.1,port=6379)>" # noqa: E501
|
|
286
|
+
)
|