redis 6.3.0__tar.gz → 6.4.0__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.3.0 → redis-6.4.0}/PKG-INFO +1 -1
- {redis-6.3.0 → redis-6.4.0}/redis/__init__.py +1 -2
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/cluster.py +0 -9
- {redis-6.3.0 → redis-6.4.0}/redis/client.py +2 -6
- redis-6.4.0/redis/commands/json/_util.py +5 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/aggregation.py +3 -3
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/commands.py +3 -3
- {redis-6.3.0 → redis-6.4.0}/redis/commands/vectorset/commands.py +7 -0
- {redis-6.3.0 → redis-6.4.0}/redis/connection.py +2 -8
- {redis-6.3.0 → redis-6.4.0}/redis/event.py +4 -4
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_vsets.py +15 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_cluster_transaction.py +2 -2
- {redis-6.3.0 → redis-6.4.0}/tests/test_connection.py +3 -3
- {redis-6.3.0 → redis-6.4.0}/tests/test_credentials.py +5 -5
- {redis-6.3.0 → redis-6.4.0}/tests/test_search.py +49 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_vsets.py +15 -0
- redis-6.3.0/redis/commands/json/_util.py +0 -3
- {redis-6.3.0 → redis-6.4.0}/.gitignore +0 -0
- {redis-6.3.0 → redis-6.4.0}/LICENSE +0 -0
- {redis-6.3.0 → redis-6.4.0}/README.md +0 -0
- {redis-6.3.0 → redis-6.4.0}/dev_requirements.txt +0 -0
- {redis-6.3.0 → redis-6.4.0}/pyproject.toml +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/base.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/encoders.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/helpers.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/hiredis.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/resp2.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/resp3.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/_parsers/socket.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/client.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/connection.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/lock.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/retry.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/sentinel.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/asyncio/utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/auth/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/auth/err.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/auth/idp.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/auth/token.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/auth/token_manager.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/backoff.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/cache.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/cluster.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/bf/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/bf/commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/bf/info.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/cluster.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/core.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/helpers.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/json/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/json/commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/json/decoders.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/json/path.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/redismodules.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/_util.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/dialect.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/document.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/field.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/index_definition.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/profile_information.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/query.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/querystring.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/reducers.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/result.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/search/suggestion.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/sentinel.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/timeseries/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/timeseries/commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/timeseries/info.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/timeseries/utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/vectorset/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/commands/vectorset/utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/crc.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/credentials.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/exceptions.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/lock.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/ocsp.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/py.typed +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/retry.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/sentinel.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/typing.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/redis/utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/conftest.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/entraid_utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/mocks.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/ssl_utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/compat.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/conftest.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/mocks.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_bloom.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_cluster.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_cluster_transaction.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_connect.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_connection.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_connection_pool.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_credentials.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_cwe_404.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_encoding.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_hash.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_json.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_lock.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_monitor.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_pipeline.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_pubsub.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_retry.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_scripting.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_search.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_sentinel.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_sentinel_managed_connection.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_ssl.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_timeseries.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/test_utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/testdata/jsontestdata.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/testdata/titles.csv +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_asyncio/testdata/will_play_text.csv.bz2 +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_auth/__init__.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_auth/test_token.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_auth/test_token_manager.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_backoff.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_bloom.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_cache.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_cluster.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_command_parser.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_commands.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_connect.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_connection_pool.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_encoding.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_function.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_hash.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_helpers.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_json.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_lock.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_max_connections_error.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_monitor.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_multiprocessing.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_parsers/test_helpers.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_pipeline.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_pubsub.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_retry.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_scripting.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_sentinel.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_sentinel_managed_connection.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_ssl.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_timeseries.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/test_utils.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/testdata/jsontestdata.py +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/testdata/titles.csv +0 -0
- {redis-6.3.0 → redis-6.4.0}/tests/testdata/will_play_text.csv.bz2 +0 -0
|
@@ -1587,15 +1587,6 @@ class ClusterPipeline(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterComm
|
|
|
1587
1587
|
def __await__(self) -> Generator[Any, None, "ClusterPipeline"]:
|
|
1588
1588
|
return self.initialize().__await__()
|
|
1589
1589
|
|
|
1590
|
-
def __enter__(self) -> "ClusterPipeline":
|
|
1591
|
-
# TODO: Remove this method before 7.0.0
|
|
1592
|
-
self._execution_strategy._command_queue = []
|
|
1593
|
-
return self
|
|
1594
|
-
|
|
1595
|
-
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None:
|
|
1596
|
-
# TODO: Remove this method before 7.0.0
|
|
1597
|
-
self._execution_strategy._command_queue = []
|
|
1598
|
-
|
|
1599
1590
|
def __bool__(self) -> bool:
|
|
1600
1591
|
"Pipeline instances should always evaluate to True on Python 3+"
|
|
1601
1592
|
return True
|
|
@@ -368,9 +368,7 @@ class Redis(RedisModuleCommands, CoreCommands, SentinelCommands):
|
|
|
368
368
|
]:
|
|
369
369
|
raise RedisError("Client caching is only supported with RESP version 3")
|
|
370
370
|
|
|
371
|
-
|
|
372
|
-
# TODO: Remove this before next major version (7.0.0)
|
|
373
|
-
self.single_connection_lock = threading.Lock()
|
|
371
|
+
self.single_connection_lock = threading.RLock()
|
|
374
372
|
self.connection = None
|
|
375
373
|
self._single_connection_client = single_connection_client
|
|
376
374
|
if self._single_connection_client:
|
|
@@ -776,9 +774,7 @@ class PubSub:
|
|
|
776
774
|
else:
|
|
777
775
|
self._event_dispatcher = event_dispatcher
|
|
778
776
|
|
|
779
|
-
|
|
780
|
-
# TODO: Remove this before next major version (7.0.0)
|
|
781
|
-
self._lock = threading.Lock()
|
|
777
|
+
self._lock = threading.RLock()
|
|
782
778
|
if self.encoder is None:
|
|
783
779
|
self.encoder = self.connection_pool.get_encoder()
|
|
784
780
|
self.health_check_response_b = self.encoder.encode(self.HEALTH_CHECK_MESSAGE)
|
|
@@ -26,7 +26,7 @@ class Reducer:
|
|
|
26
26
|
|
|
27
27
|
NAME = None
|
|
28
28
|
|
|
29
|
-
def __init__(self, *args:
|
|
29
|
+
def __init__(self, *args: str) -> None:
|
|
30
30
|
self._args = args
|
|
31
31
|
self._field = None
|
|
32
32
|
self._alias = None
|
|
@@ -116,7 +116,7 @@ class AggregateRequest:
|
|
|
116
116
|
self._add_scores = False
|
|
117
117
|
self._scorer = "TFIDF"
|
|
118
118
|
|
|
119
|
-
def load(self, *fields:
|
|
119
|
+
def load(self, *fields: str) -> "AggregateRequest":
|
|
120
120
|
"""
|
|
121
121
|
Indicate the fields to be returned in the response. These fields are
|
|
122
122
|
returned in addition to any others implicitly specified.
|
|
@@ -223,7 +223,7 @@ class AggregateRequest:
|
|
|
223
223
|
self._aggregateplan.extend(_limit.build_args())
|
|
224
224
|
return self
|
|
225
225
|
|
|
226
|
-
def sort_by(self, *fields:
|
|
226
|
+
def sort_by(self, *fields: str, **kwargs) -> "AggregateRequest":
|
|
227
227
|
"""
|
|
228
228
|
Indicate how the results should be sorted. This can also be used for
|
|
229
229
|
*top-N* style queries
|
|
@@ -542,7 +542,7 @@ class SearchCommands:
|
|
|
542
542
|
|
|
543
543
|
def aggregate(
|
|
544
544
|
self,
|
|
545
|
-
query: Union[
|
|
545
|
+
query: Union[AggregateRequest, Cursor],
|
|
546
546
|
query_params: Dict[str, Union[str, int, float]] = None,
|
|
547
547
|
):
|
|
548
548
|
"""
|
|
@@ -573,7 +573,7 @@ class SearchCommands:
|
|
|
573
573
|
)
|
|
574
574
|
|
|
575
575
|
def _get_aggregate_result(
|
|
576
|
-
self, raw: List, query: Union[
|
|
576
|
+
self, raw: List, query: Union[AggregateRequest, Cursor], has_cursor: bool
|
|
577
577
|
):
|
|
578
578
|
if has_cursor:
|
|
579
579
|
if isinstance(query, Cursor):
|
|
@@ -967,7 +967,7 @@ class AsyncSearchCommands(SearchCommands):
|
|
|
967
967
|
|
|
968
968
|
async def aggregate(
|
|
969
969
|
self,
|
|
970
|
-
query: Union[
|
|
970
|
+
query: Union[AggregateResult, Cursor],
|
|
971
971
|
query_params: Dict[str, Union[str, int, float]] = None,
|
|
972
972
|
):
|
|
973
973
|
"""
|
|
@@ -129,6 +129,7 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
129
129
|
filter_ef: Optional[str] = None,
|
|
130
130
|
truth: Optional[bool] = False,
|
|
131
131
|
no_thread: Optional[bool] = False,
|
|
132
|
+
epsilon: Optional[Number] = None,
|
|
132
133
|
) -> Union[
|
|
133
134
|
Awaitable[Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]]],
|
|
134
135
|
Optional[List[Union[List[EncodableT], Dict[EncodableT, Number]]]],
|
|
@@ -152,6 +153,9 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
152
153
|
``no_thread`` when enabled forces the command to execute the search
|
|
153
154
|
on the data structure in the main thread.
|
|
154
155
|
|
|
156
|
+
``epsilon`` floating point between 0 and 1, if specified will return
|
|
157
|
+
only elements with distance no further than the specified one.
|
|
158
|
+
|
|
155
159
|
For more information see https://redis.io/commands/vsim
|
|
156
160
|
"""
|
|
157
161
|
|
|
@@ -176,6 +180,9 @@ class VectorSetCommands(CommandsProtocol):
|
|
|
176
180
|
if count:
|
|
177
181
|
pieces.extend(["COUNT", count])
|
|
178
182
|
|
|
183
|
+
if epsilon:
|
|
184
|
+
pieces.extend(["EPSILON", epsilon])
|
|
185
|
+
|
|
179
186
|
if ef:
|
|
180
187
|
pieces.extend(["EF", ef])
|
|
181
188
|
|
|
@@ -816,7 +816,7 @@ class CacheProxyConnection(ConnectionInterface):
|
|
|
816
816
|
self,
|
|
817
817
|
conn: ConnectionInterface,
|
|
818
818
|
cache: CacheInterface,
|
|
819
|
-
pool_lock: threading.
|
|
819
|
+
pool_lock: threading.RLock,
|
|
820
820
|
):
|
|
821
821
|
self.pid = os.getpid()
|
|
822
822
|
self._conn = conn
|
|
@@ -1429,13 +1429,7 @@ class ConnectionPool:
|
|
|
1429
1429
|
# release the lock.
|
|
1430
1430
|
|
|
1431
1431
|
self._fork_lock = threading.RLock()
|
|
1432
|
-
|
|
1433
|
-
if self.cache is None:
|
|
1434
|
-
self._lock = threading.RLock()
|
|
1435
|
-
else:
|
|
1436
|
-
# TODO: To avoid breaking changes during the bug fix, we have to keep non-reentrant lock.
|
|
1437
|
-
# TODO: Remove this before next major version (7.0.0)
|
|
1438
|
-
self._lock = threading.Lock()
|
|
1432
|
+
self._lock = threading.RLock()
|
|
1439
1433
|
|
|
1440
1434
|
self.reset()
|
|
1441
1435
|
|
|
@@ -152,7 +152,7 @@ class AfterSingleConnectionInstantiationEvent:
|
|
|
152
152
|
self,
|
|
153
153
|
connection,
|
|
154
154
|
client_type: ClientType,
|
|
155
|
-
connection_lock: Union[threading.
|
|
155
|
+
connection_lock: Union[threading.RLock, asyncio.Lock],
|
|
156
156
|
):
|
|
157
157
|
self._connection = connection
|
|
158
158
|
self._client_type = client_type
|
|
@@ -167,7 +167,7 @@ class AfterSingleConnectionInstantiationEvent:
|
|
|
167
167
|
return self._client_type
|
|
168
168
|
|
|
169
169
|
@property
|
|
170
|
-
def connection_lock(self) -> Union[threading.
|
|
170
|
+
def connection_lock(self) -> Union[threading.RLock, asyncio.Lock]:
|
|
171
171
|
return self._connection_lock
|
|
172
172
|
|
|
173
173
|
|
|
@@ -177,7 +177,7 @@ class AfterPubSubConnectionInstantiationEvent:
|
|
|
177
177
|
pubsub_connection,
|
|
178
178
|
connection_pool,
|
|
179
179
|
client_type: ClientType,
|
|
180
|
-
connection_lock: Union[threading.
|
|
180
|
+
connection_lock: Union[threading.RLock, asyncio.Lock],
|
|
181
181
|
):
|
|
182
182
|
self._pubsub_connection = pubsub_connection
|
|
183
183
|
self._connection_pool = connection_pool
|
|
@@ -197,7 +197,7 @@ class AfterPubSubConnectionInstantiationEvent:
|
|
|
197
197
|
return self._client_type
|
|
198
198
|
|
|
199
199
|
@property
|
|
200
|
-
def connection_lock(self) -> Union[threading.
|
|
200
|
+
def connection_lock(self) -> Union[threading.RLock, asyncio.Lock]:
|
|
201
201
|
return self._connection_lock
|
|
202
202
|
|
|
203
203
|
|
|
@@ -423,6 +423,21 @@ async def test_vsim_truth_no_thread_enabled(d_client):
|
|
|
423
423
|
assert isinstance(sim_no_thread, dict)
|
|
424
424
|
|
|
425
425
|
|
|
426
|
+
@skip_if_server_version_lt("8.2.0")
|
|
427
|
+
async def test_vsim_epsilon(d_client):
|
|
428
|
+
await d_client.vset().vadd("myset", [2, 1, 1], "a")
|
|
429
|
+
await d_client.vset().vadd("myset", [2, 0, 1], "b")
|
|
430
|
+
await d_client.vset().vadd("myset", [2, 0, 0], "c")
|
|
431
|
+
await d_client.vset().vadd("myset", [2, 0, -1], "d")
|
|
432
|
+
await d_client.vset().vadd("myset", [2, -1, -1], "e")
|
|
433
|
+
|
|
434
|
+
res1 = await d_client.vset().vsim("myset", [2, 1, 1])
|
|
435
|
+
assert 5 == len(res1)
|
|
436
|
+
|
|
437
|
+
res2 = await d_client.vset().vsim("myset", [2, 1, 1], epsilon=0.5)
|
|
438
|
+
assert 4 == len(res2)
|
|
439
|
+
|
|
440
|
+
|
|
426
441
|
@skip_if_server_version_lt("7.9.0")
|
|
427
442
|
async def test_vdim(d_client):
|
|
428
443
|
float_array = [1, 4.32, 0.11, 0.5, 0.9, 0.1, 0.2]
|
|
@@ -285,7 +285,7 @@ class TestClusterTransaction:
|
|
|
285
285
|
mock_pool = Mock(spec=ConnectionPool)
|
|
286
286
|
mock_pool.get_connection.return_value = mock_connection
|
|
287
287
|
mock_pool._available_connections = [mock_connection]
|
|
288
|
-
mock_pool._lock = threading.
|
|
288
|
+
mock_pool._lock = threading.RLock()
|
|
289
289
|
|
|
290
290
|
_node_migrating, node_importing = _find_source_and_target_node_for_slot(r, slot)
|
|
291
291
|
node_importing.redis_connection.connection_pool = mock_pool
|
|
@@ -310,7 +310,7 @@ class TestClusterTransaction:
|
|
|
310
310
|
mock_pool = Mock(spec=ConnectionPool)
|
|
311
311
|
mock_pool.get_connection.return_value = mock_connection
|
|
312
312
|
mock_pool._available_connections = [mock_connection]
|
|
313
|
-
mock_pool._lock = threading.
|
|
313
|
+
mock_pool._lock = threading.RLock()
|
|
314
314
|
|
|
315
315
|
_node_migrating, node_importing = _find_source_and_target_node_for_slot(r, slot)
|
|
316
316
|
node_importing.redis_connection.connection_pool = mock_pool
|
|
@@ -442,7 +442,7 @@ class TestUnitCacheProxyConnection:
|
|
|
442
442
|
mock_connection.credential_provider = UsernamePasswordCredentialProvider()
|
|
443
443
|
|
|
444
444
|
proxy_connection = CacheProxyConnection(
|
|
445
|
-
mock_connection, cache, threading.
|
|
445
|
+
mock_connection, cache, threading.RLock()
|
|
446
446
|
)
|
|
447
447
|
proxy_connection.disconnect()
|
|
448
448
|
|
|
@@ -492,7 +492,7 @@ class TestUnitCacheProxyConnection:
|
|
|
492
492
|
mock_connection.can_read.return_value = False
|
|
493
493
|
|
|
494
494
|
proxy_connection = CacheProxyConnection(
|
|
495
|
-
mock_connection, mock_cache, threading.
|
|
495
|
+
mock_connection, mock_cache, threading.RLock()
|
|
496
496
|
)
|
|
497
497
|
proxy_connection.send_command(*["GET", "foo"], **{"keys": ["foo"]})
|
|
498
498
|
assert proxy_connection.read_response() == b"bar"
|
|
@@ -554,7 +554,7 @@ class TestUnitCacheProxyConnection:
|
|
|
554
554
|
mock_connection.can_read.return_value = False
|
|
555
555
|
|
|
556
556
|
proxy_connection = CacheProxyConnection(
|
|
557
|
-
mock_connection, mock_cache, threading.
|
|
557
|
+
mock_connection, mock_cache, threading.RLock()
|
|
558
558
|
)
|
|
559
559
|
proxy_connection.send_command(*["GET", "foo"], **{"keys": ["foo"]})
|
|
560
560
|
|
|
@@ -323,7 +323,7 @@ class TestStreamingCredentialProvider:
|
|
|
323
323
|
}
|
|
324
324
|
mock_pool.get_connection.return_value = mock_connection
|
|
325
325
|
mock_pool._available_connections = [mock_connection, mock_another_connection]
|
|
326
|
-
mock_pool._lock = threading.
|
|
326
|
+
mock_pool._lock = threading.RLock()
|
|
327
327
|
auth_token = None
|
|
328
328
|
|
|
329
329
|
def re_auth_callback(token):
|
|
@@ -382,7 +382,7 @@ class TestStreamingCredentialProvider:
|
|
|
382
382
|
mock_another_connection,
|
|
383
383
|
mock_failed_connection,
|
|
384
384
|
]
|
|
385
|
-
mock_pool._lock = threading.
|
|
385
|
+
mock_pool._lock = threading.RLock()
|
|
386
386
|
|
|
387
387
|
def _raise(error: RedisError):
|
|
388
388
|
pass
|
|
@@ -442,7 +442,7 @@ class TestStreamingCredentialProvider:
|
|
|
442
442
|
mock_another_connection,
|
|
443
443
|
]
|
|
444
444
|
mock_pool._available_connections = [mock_another_connection]
|
|
445
|
-
mock_pool._lock = threading.
|
|
445
|
+
mock_pool._lock = threading.RLock()
|
|
446
446
|
auth_token = None
|
|
447
447
|
|
|
448
448
|
def re_auth_callback(token):
|
|
@@ -502,7 +502,7 @@ class TestStreamingCredentialProvider:
|
|
|
502
502
|
mock_another_connection,
|
|
503
503
|
]
|
|
504
504
|
mock_pool._available_connections = [mock_another_connection]
|
|
505
|
-
mock_pool._lock = threading.
|
|
505
|
+
mock_pool._lock = threading.RLock()
|
|
506
506
|
auth_token = None
|
|
507
507
|
|
|
508
508
|
def re_auth_callback(token):
|
|
@@ -560,7 +560,7 @@ class TestStreamingCredentialProvider:
|
|
|
560
560
|
}
|
|
561
561
|
mock_pool.get_connection.return_value = mock_connection
|
|
562
562
|
mock_pool._available_connections = [mock_connection, mock_another_connection]
|
|
563
|
-
mock_pool._lock = threading.
|
|
563
|
+
mock_pool._lock = threading.RLock()
|
|
564
564
|
|
|
565
565
|
Redis(
|
|
566
566
|
connection_pool=mock_pool,
|
|
@@ -3802,3 +3802,52 @@ def test_svs_vamana_vector_search_with_parameters(client):
|
|
|
3802
3802
|
else:
|
|
3803
3803
|
assert res["total_results"] == 3
|
|
3804
3804
|
assert "doc0" == res["results"][0]["id"]
|
|
3805
|
+
|
|
3806
|
+
|
|
3807
|
+
@pytest.mark.redismod
|
|
3808
|
+
@skip_ifmodversion_lt("2.4.3", "search")
|
|
3809
|
+
@skip_if_server_version_lt("8.1.224")
|
|
3810
|
+
def test_svs_vamana_vector_search_with_parameters_leanvec(client):
|
|
3811
|
+
client.ft().create_index(
|
|
3812
|
+
(
|
|
3813
|
+
VectorField(
|
|
3814
|
+
"v",
|
|
3815
|
+
"SVS-VAMANA",
|
|
3816
|
+
{
|
|
3817
|
+
"TYPE": "FLOAT32",
|
|
3818
|
+
"DIM": 8,
|
|
3819
|
+
"DISTANCE_METRIC": "L2",
|
|
3820
|
+
"COMPRESSION": "LeanVec8x8", # LeanVec compression required for REDUCE
|
|
3821
|
+
"CONSTRUCTION_WINDOW_SIZE": 200,
|
|
3822
|
+
"GRAPH_MAX_DEGREE": 32,
|
|
3823
|
+
"SEARCH_WINDOW_SIZE": 15,
|
|
3824
|
+
"EPSILON": 0.01,
|
|
3825
|
+
"TRAINING_THRESHOLD": 1024,
|
|
3826
|
+
"REDUCE": 4, # Half of DIM (8/2 = 4)
|
|
3827
|
+
},
|
|
3828
|
+
),
|
|
3829
|
+
)
|
|
3830
|
+
)
|
|
3831
|
+
|
|
3832
|
+
# Create test vectors (8-dimensional to match DIM)
|
|
3833
|
+
vectors = [
|
|
3834
|
+
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
|
|
3835
|
+
[2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
|
|
3836
|
+
[3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
|
|
3837
|
+
[4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0],
|
|
3838
|
+
[5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0],
|
|
3839
|
+
]
|
|
3840
|
+
|
|
3841
|
+
for i, vec in enumerate(vectors):
|
|
3842
|
+
client.hset(f"doc{i}", "v", np.array(vec, dtype=np.float32).tobytes())
|
|
3843
|
+
|
|
3844
|
+
query = Query("*=>[KNN 3 @v $vec as score]").no_content()
|
|
3845
|
+
query_params = {"vec": np.array(vectors[0], dtype=np.float32).tobytes()}
|
|
3846
|
+
|
|
3847
|
+
res = client.ft().search(query, query_params=query_params)
|
|
3848
|
+
if is_resp2_connection(client):
|
|
3849
|
+
assert res.total == 3
|
|
3850
|
+
assert "doc0" == res.docs[0].id
|
|
3851
|
+
else:
|
|
3852
|
+
assert res["total_results"] == 3
|
|
3853
|
+
assert "doc0" == res["results"][0]["id"]
|
|
@@ -425,6 +425,21 @@ def test_vsim_truth_no_thread_enabled(d_client):
|
|
|
425
425
|
assert isinstance(sim_no_thread, dict)
|
|
426
426
|
|
|
427
427
|
|
|
428
|
+
@skip_if_server_version_lt("8.2.0")
|
|
429
|
+
def test_vsim_epsilon(d_client):
|
|
430
|
+
d_client.vset().vadd("myset", [2, 1, 1], "a")
|
|
431
|
+
d_client.vset().vadd("myset", [2, 0, 1], "b")
|
|
432
|
+
d_client.vset().vadd("myset", [2, 0, 0], "c")
|
|
433
|
+
d_client.vset().vadd("myset", [2, 0, -1], "d")
|
|
434
|
+
d_client.vset().vadd("myset", [2, -1, -1], "e")
|
|
435
|
+
|
|
436
|
+
res1 = d_client.vset().vsim("myset", [2, 1, 1])
|
|
437
|
+
assert 5 == len(res1)
|
|
438
|
+
|
|
439
|
+
res2 = d_client.vset().vsim("myset", [2, 1, 1], epsilon=0.5)
|
|
440
|
+
assert 4 == len(res2)
|
|
441
|
+
|
|
442
|
+
|
|
428
443
|
@skip_if_server_version_lt("7.9.0")
|
|
429
444
|
def test_vdim(d_client):
|
|
430
445
|
float_array = [1, 4.32, 0.11, 0.5, 0.9, 0.1, 0.2]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|