Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-redis for openSUSE:Factory 
checked in at 2025-02-14 19:19:23
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-redis (Old)
 and      /work/SRC/openSUSE:Factory/.python-redis.new.8181 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-redis"

Fri Feb 14 19:19:23 2025 rev:44 rq:1245617 version:5.2.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-redis/python-redis.changes        
2024-11-29 00:08:55.681545987 +0100
+++ /work/SRC/openSUSE:Factory/.python-redis.new.8181/python-redis.changes      
2025-02-14 19:19:24.743006662 +0100
@@ -1,0 +2,12 @@
+Thu Feb 13 10:59:14 UTC 2025 - Daniel Garcia <[email protected]>
+
+- Add pytest-asyncio-045.patch to make tests compatible with latest
+  python-pytest-asyncio
+- Update to 5.2.1:
+  * Fixed unsecured tempfile.mktemp() command usage (#3446)
+  * Fixed bug with SLOWLOG GET response parsing on Redis Software (#3441)
+  * Fixed issue with invoking _close() on closed event loop (#3438)
+  * Migrate test infrastructure to new custom docker images (#3415)
+  * Fixed flacky test with HEXPIREAT command (#3437)
+
+-------------------------------------------------------------------

Old:
----
  redis-5.2.0.tar.gz

New:
----
  pytest-asyncio-045.patch
  redis-5.2.1.tar.gz

BETA DEBUG BEGIN:
  New:
- Add pytest-asyncio-045.patch to make tests compatible with latest
  python-pytest-asyncio
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-redis.spec ++++++
--- /var/tmp/diff_new_pack.yjSD2r/_old  2025-02-14 19:19:26.079061971 +0100
+++ /var/tmp/diff_new_pack.yjSD2r/_new  2025-02-14 19:19:26.083062137 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-redis
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-redis
-Version:        5.2.0
+Version:        5.2.1
 Release:        0
 Summary:        Python client for Redis key-value store
 License:        MIT
@@ -28,12 +28,14 @@
 Source0:        
https://files.pythonhosted.org/packages/source/r/redis/redis-%{version}.tar.gz
 Source1:        
https://github.com/redis/redis-py/raw/refs/tags/v%{version}/pytest.ini
 Patch0:         increase-test-timeout.patch
+# PATCH-FIX-OPENSUSE pytest-asyncio-045.patch
+Patch1:         pytest-asyncio-045.patch
 BuildRequires:  %{python_module async-timeout >= 4.0.2 if %python-base < 
3.11.3}
 BuildRequires:  %{python_module base >= 3.7}
 BuildRequires:  %{python_module numpy}
 BuildRequires:  %{python_module packaging}
 BuildRequires:  %{python_module pip}
-BuildRequires:  %{python_module pytest-asyncio < 0.24}
+BuildRequires:  %{python_module pytest-asyncio}
 BuildRequires:  %{python_module pytest-timeout}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
@@ -60,6 +62,7 @@
 %ifarch s390x
 %patch -P 0 -p1
 %endif
+%patch -P 1 -p2
 
 # These tests pass locally but fail in obs with different
 # environment, like ALP build...
@@ -105,7 +108,7 @@
 donttest="$donttest or test_xautoclaim"
 # gh#redis/redis-py#2679
 donttest+=" or test_acl_getuser_setuser or test_acl_log"
-%pytest -m 'not (onlycluster or redismod or ssl)' -k "not ($donttest)" 
--ignore tests/test_ssl.py --ignore tests/test_asyncio/test_cluster.py 
--redis-url=redis://localhost:6379/
+%pytest -m 'not (onlycluster or redismod or ssl or graph)' -k "not 
($donttest)" --ignore tests/test_ssl.py --ignore 
tests/test_asyncio/test_cluster.py --redis-url=redis://localhost:6379/
 %endif
 
 %files %{python_files}

++++++ pytest-asyncio-045.patch ++++++
Index: python-redis/redis-5.2.1/tests/test_asyncio/test_scripting.py
===================================================================
--- python-redis.orig/redis-5.2.1/tests/test_asyncio/test_scripting.py
+++ python-redis/redis-5.2.1/tests/test_asyncio/test_scripting.py
@@ -28,14 +28,14 @@ class TestScripting:
         yield redis
         await redis.script_flush()
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_eval(self, r):
         await r.flushdb()
         await r.set("a", 2)
         # 2 * 3 == 6
         assert await r.eval(multiply_script, 1, "a", 3) == 6
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     @skip_if_server_version_lt("6.2.0")
     async def test_script_flush(self, r):
         await r.set("a", 2)
@@ -55,14 +55,14 @@ class TestScripting:
             await r.script_load(multiply_script)
             await r.script_flush("NOTREAL")
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_evalsha(self, r):
         await r.set("a", 2)
         sha = await r.script_load(multiply_script)
         # 2 * 3 == 6
         assert await r.evalsha(sha, 1, "a", 3) == 6
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_evalsha_script_not_loaded(self, r):
         await r.set("a", 2)
         sha = await r.script_load(multiply_script)
@@ -71,7 +71,7 @@ class TestScripting:
         with pytest.raises(exceptions.NoScriptError):
             await r.evalsha(sha, 1, "a", 3)
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_script_loading(self, r):
         # get the sha, then clear the cache
         sha = await r.script_load(multiply_script)
@@ -80,7 +80,7 @@ class TestScripting:
         await r.script_load(multiply_script)
         assert await r.script_exists(sha) == [True]
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_script_object(self, r):
         await r.script_flush()
         await r.set("a", 2)
@@ -97,7 +97,7 @@ class TestScripting:
         # Test first evalsha block
         assert await multiply(keys=["a"], args=[3]) == 6
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_script_object_in_pipeline(self, r):
         await r.script_flush()
         multiply = r.register_script(multiply_script)
@@ -127,7 +127,7 @@ class TestScripting:
         assert await pipe.execute() == [True, b"2", 6]
         assert await r.script_exists(multiply.sha) == [True]
 
-    @pytest.mark.asyncio(forbid_global_loop=True)
+    @pytest.mark.asyncio()
     async def test_eval_msgpack_pipeline_error_in_lua(self, r):
         msgpack_hello = r.register_script(msgpack_hello_script)
         assert msgpack_hello.sha

++++++ pytest.ini ++++++
--- /var/tmp/diff_new_pack.yjSD2r/_old  2025-02-14 19:19:26.123063793 +0100
+++ /var/tmp/diff_new_pack.yjSD2r/_new  2025-02-14 19:19:26.127063958 +0100
@@ -2,6 +2,7 @@
 addopts = -s
 markers =
     redismod: run only the redis module tests
+    graph: run only the redisgraph tests
     pipeline: pipeline tests
     onlycluster: marks tests to be run only with cluster mode redis
     onlynoncluster: marks tests to be run only with standalone redis

++++++ redis-5.2.0.tar.gz -> redis-5.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/PKG-INFO new/redis-5.2.1/PKG-INFO
--- old/redis-5.2.0/PKG-INFO    2024-10-24 17:04:18.078694800 +0200
+++ new/redis-5.2.1/PKG-INFO    2024-12-06 10:50:31.494830600 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: redis
-Version: 5.2.0
+Version: 5.2.1
 Summary: Python client for Redis database and key-value store
 Home-page: https://github.com/redis/redis-py
 Author: Redis Inc.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/redis/_parsers/helpers.py 
new/redis-5.2.1/redis/_parsers/helpers.py
--- old/redis-5.2.0/redis/_parsers/helpers.py   2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/redis/_parsers/helpers.py   2024-12-06 10:50:17.000000000 
+0100
@@ -396,13 +396,20 @@
         # an O(N) complexity) instead of the command.
         if isinstance(item[3], list):
             result["command"] = space.join(item[3])
-            result["client_address"] = item[4]
-            result["client_name"] = item[5]
+
+            # These fields are optional, depends on environment.
+            if len(item) >= 6:
+                result["client_address"] = item[4]
+                result["client_name"] = item[5]
         else:
             result["complexity"] = item[3]
             result["command"] = space.join(item[4])
-            result["client_address"] = item[5]
-            result["client_name"] = item[6]
+
+            # These fields are optional, depends on environment.
+            if len(item) >= 7:
+                result["client_address"] = item[5]
+                result["client_name"] = item[6]
+
         return result
 
     return [parse_item(item) for item in response]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/redis/asyncio/connection.py 
new/redis-5.2.1/redis/asyncio/connection.py
--- old/redis-5.2.0/redis/asyncio/connection.py 2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/redis/asyncio/connection.py 2024-12-06 10:50:17.000000000 
+0100
@@ -214,7 +214,13 @@
             _warnings.warn(
                 f"unclosed Connection {self!r}", ResourceWarning, source=self
             )
-            self._close()
+
+            try:
+                asyncio.get_running_loop()
+                self._close()
+            except RuntimeError:
+                # No actions been taken if pool already closed.
+                pass
 
     def _close(self):
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/redis/asyncio/sentinel.py 
new/redis-5.2.1/redis/asyncio/sentinel.py
--- old/redis-5.2.0/redis/asyncio/sentinel.py   2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/redis/asyncio/sentinel.py   2024-12-06 10:50:17.000000000 
+0100
@@ -29,11 +29,7 @@
         super().__init__(**kwargs)
 
     def __repr__(self):
-        pool = self.connection_pool
-        s = (
-            f"<{self.__class__.__module__}.{self.__class__.__name__}"
-            f"(service={pool.service_name}"
-        )
+        s = f"<{self.__class__.__module__}.{self.__class__.__name__}"
         if self.host:
             host_info = f",host={self.host},port={self.port}"
             s += host_info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/redis.egg-info/PKG-INFO 
new/redis-5.2.1/redis.egg-info/PKG-INFO
--- old/redis-5.2.0/redis.egg-info/PKG-INFO     2024-10-24 17:04:18.000000000 
+0200
+++ new/redis-5.2.1/redis.egg-info/PKG-INFO     2024-12-06 10:50:31.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: redis
-Version: 5.2.0
+Version: 5.2.1
 Summary: Python client for Redis database and key-value store
 Home-page: https://github.com/redis/redis-py
 Author: Redis Inc.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/setup.py new/redis-5.2.1/setup.py
--- old/redis-5.2.0/setup.py    2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/setup.py    2024-12-06 10:50:17.000000000 +0100
@@ -8,7 +8,7 @@
     long_description_content_type="text/markdown",
     keywords=["Redis", "key-value store", "database"],
     license="MIT",
-    version="5.2.0",
+    version="5.2.1",
     packages=find_packages(
         include=[
             "redis",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/conftest.py 
new/redis-5.2.1/tests/conftest.py
--- old/redis-5.2.0/tests/conftest.py   2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/conftest.py   2024-12-06 10:50:17.000000000 +0100
@@ -21,7 +21,7 @@
 from redis.connection import Connection, ConnectionInterface, SSLConnection, 
parse_url
 from redis.exceptions import RedisClusterException
 from redis.retry import Retry
-from tests.ssl_utils import get_ssl_filename
+from tests.ssl_utils import get_tls_certificates
 
 REDIS_INFO = {}
 default_redis_url = "redis://localhost:6379/0"
@@ -104,6 +104,13 @@
     )
 
     parser.addoption(
+        "--redis-mod-url",
+        default=default_redismod_url,
+        action="store",
+        help="Redis with modules connection string, defaults to `%(default)s`",
+    )
+
+    parser.addoption(
         "--protocol",
         default=default_protocol,
         action="store",
@@ -177,14 +184,14 @@
     REDIS_INFO["version"] = version
     REDIS_INFO["arch_bits"] = arch_bits
     REDIS_INFO["cluster_enabled"] = cluster_enabled
+    REDIS_INFO["tls_cert_subdir"] = "cluster" if cluster_enabled else 
"standalone"
     REDIS_INFO["enterprise"] = enterprise
     # store REDIS_INFO in config so that it is available from "condition 
strings"
     session.config.REDIS_INFO = REDIS_INFO
 
     # module info
-    stack_url = redis_url
-    if stack_url == default_redis_url:
-        stack_url = default_redismod_url
+    stack_url = session.config.getoption("--redis-mod-url")
+
     try:
         stack_info = _get_info(stack_url)
         REDIS_INFO["modules"] = stack_info["modules"]
@@ -325,6 +332,9 @@
         redis_url = request.config.getoption("--redis-url")
     else:
         redis_url = from_url
+
+    redis_tls_url = request.config.getoption("--redis-ssl-url")
+
     if "protocol" not in redis_url and kwargs.get("protocol") is None:
         kwargs["protocol"] = request.config.getoption("--protocol")
 
@@ -335,15 +345,11 @@
         connection_class = Connection
         if ssl:
             connection_class = SSLConnection
-            kwargs["ssl_certfile"] = get_ssl_filename("client-cert.pem")
-            kwargs["ssl_keyfile"] = get_ssl_filename("client-key.pem")
-            # When you try to assign "required" as single string
-            # it assigns tuple instead of string.
-            # Probably some reserved keyword
-            # I can't explain how does it work -_-
-            kwargs["ssl_cert_reqs"] = "require" + "d"
-            kwargs["ssl_ca_certs"] = get_ssl_filename("ca-cert.pem")
-            kwargs["port"] = 6666
+            kwargs["ssl_certfile"], kwargs["ssl_keyfile"], 
kwargs["ssl_ca_certs"] = (
+                get_tls_certificates()
+            )
+            kwargs["ssl_cert_reqs"] = "required"
+            kwargs["port"] = urlparse(redis_tls_url).port
         kwargs["connection_class"] = connection_class
         url_options.update(kwargs)
         pool = redis.ConnectionPool(**url_options)
@@ -393,11 +399,7 @@
 
 @pytest.fixture()
 def stack_url(request):
-    stack_url = request.config.getoption("--redis-url", 
default=default_redismod_url)
-    if stack_url == default_redis_url:
-        return default_redismod_url
-    else:
-        return stack_url
+    return request.config.getoption("--redis-mod-url", 
default=default_redismod_url)
 
 
 @pytest.fixture()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/ssl_utils.py 
new/redis-5.2.1/tests/ssl_utils.py
--- old/redis-5.2.0/tests/ssl_utils.py  2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/ssl_utils.py  2024-12-06 10:50:17.000000000 +0100
@@ -1,14 +1,43 @@
+import enum
 import os
+from collections import namedtuple
 
+CLIENT_CERT_NAME = "client.crt"
+CLIENT_KEY_NAME = "client.key"
+SERVER_CERT_NAME = "redis.crt"
+SERVER_KEY_NAME = "redis.key"
+CA_CERT_NAME = "ca.crt"
 
-def get_ssl_filename(name):
+
+class CertificateType(str, enum.Enum):
+    client = "client"
+    server = "server"
+
+
+TLSFiles = namedtuple("TLSFiles", ["certfile", "keyfile", "ca_certfile"])
+
+
+def get_tls_certificates(
+    subdir: str = "standalone",
+    cert_type: CertificateType = CertificateType.client,
+):
     root = os.path.join(os.path.dirname(__file__), "..")
-    cert_dir = os.path.abspath(os.path.join(root, "dockers", "stunnel", 
"keys"))
+    cert_subdir = ("dockers", subdir, "tls")
+    cert_dir = os.path.abspath(os.path.join(root, *cert_subdir))
     if not os.path.isdir(cert_dir):  # github actions package validation case
-        cert_dir = os.path.abspath(
-            os.path.join(root, "..", "dockers", "stunnel", "keys")
-        )
+        cert_dir = os.path.abspath(os.path.join(root, "..", *cert_subdir))
         if not os.path.isdir(cert_dir):
             raise OSError(f"No SSL certificates found. They should be in 
{cert_dir}")
 
-    return os.path.join(cert_dir, name)
+    if cert_type == CertificateType.client:
+        return TLSFiles(
+            os.path.join(cert_dir, CLIENT_CERT_NAME),
+            os.path.join(cert_dir, CLIENT_KEY_NAME),
+            os.path.join(cert_dir, CA_CERT_NAME),
+        )
+    elif cert_type == CertificateType.server:
+        return TLSFiles(
+            os.path.join(cert_dir, SERVER_CERT_NAME),
+            os.path.join(cert_dir, SERVER_KEY_NAME),
+            os.path.join(cert_dir, CA_CERT_NAME),
+        )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_cluster.py 
new/redis-5.2.1/tests/test_asyncio/test_cluster.py
--- old/redis-5.2.0/tests/test_asyncio/test_cluster.py  2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_cluster.py  2024-12-06 
10:50:17.000000000 +0100
@@ -33,12 +33,11 @@
     assert_resp_response,
     is_resp2_connection,
     skip_if_redis_enterprise,
-    skip_if_server_version_gte,
     skip_if_server_version_lt,
     skip_unless_arch_bits,
 )
 
-from ..ssl_utils import get_ssl_filename
+from ..ssl_utils import get_tls_certificates
 from .compat import aclosing, mock
 
 pytestmark = pytest.mark.onlycluster
@@ -380,20 +379,22 @@
         async with RedisCluster.from_url(url) as rc_default:
             # Test default retry
             retry = rc_default.connection_kwargs.get("retry")
+
+            # FIXME: Workaround for 
https://github.com/redis/redis-py/issues/3030
+            host = rc_default.get_default_node().host
+
             assert isinstance(retry, Retry)
             assert retry._retries == 3
             assert isinstance(retry._backoff, type(default_backoff()))
-            assert rc_default.get_node("127.0.0.1", 
16379).connection_kwargs.get(
+            assert rc_default.get_node(host, 16379).connection_kwargs.get(
                 "retry"
-            ) == rc_default.get_node("127.0.0.1", 
16380).connection_kwargs.get("retry")
+            ) == rc_default.get_node(host, 
16380).connection_kwargs.get("retry")
 
         retry = Retry(ExponentialBackoff(10, 5), 5)
         async with RedisCluster.from_url(url, retry=retry) as rc_custom_retry:
             # Test custom retry
             assert (
-                rc_custom_retry.get_node("127.0.0.1", 
16379).connection_kwargs.get(
-                    "retry"
-                )
+                rc_custom_retry.get_node(host, 
16379).connection_kwargs.get("retry")
                 == retry
             )
 
@@ -402,9 +403,7 @@
         ) as rc_no_retries:
             # Test no connection retries
             assert (
-                rc_no_retries.get_node("127.0.0.1", 
16379).connection_kwargs.get(
-                    "retry"
-                )
+                rc_no_retries.get_node(host, 
16379).connection_kwargs.get("retry")
                 is None
             )
 
@@ -412,7 +411,7 @@
             url, retry=Retry(NoBackoff(), 0)
         ) as rc_no_retries:
             assert (
-                rc_no_retries.get_node("127.0.0.1", 16379)
+                rc_no_retries.get_node(host, 16379)
                 .connection_kwargs.get("retry")
                 ._retries
                 == 0
@@ -493,8 +492,8 @@
         Test command execution with nodes flag REPLICAS
         """
         replicas = r.get_replicas()
-        if not replicas:
-            r = await get_mocked_redis_client(default_host, default_port)
+        assert len(replicas) != 0, "This test requires Cluster with 1 replica"
+
         primaries = r.get_primaries()
         mock_all_nodes_resp(r, "PONG")
         assert await r.ping(target_nodes=RedisCluster.REPLICAS) is True
@@ -2804,7 +2803,6 @@
             assert ask_node._free.pop().read_response.await_count
             assert res == ["MOCK_OK"]
 
-    @skip_if_server_version_gte("7.0.0")
     async def test_moved_redirection_on_slave_with_default(
         self, r: RedisCluster
     ) -> None:
@@ -2824,11 +2822,7 @@
             async def parse_response(
                 self, connection: Connection, command: str, **kwargs: Any
             ) -> Any:
-                if (
-                    command == "GET"
-                    and self.host != primary.host
-                    and self.port != primary.port
-                ):
+                if command == "GET" and self.port != primary.port:
                     raise MovedError(moved_error)
 
                 return await parse_response_orig(connection, command, **kwargs)
@@ -2899,9 +2893,7 @@
     appropriate port.
     """
 
-    CA_CERT = get_ssl_filename("ca-cert.pem")
-    CLIENT_CERT = get_ssl_filename("client-cert.pem")
-    CLIENT_KEY = get_ssl_filename("client-key.pem")
+    CLIENT_CERT, CLIENT_KEY, CA_CERT = get_tls_certificates("cluster")
 
     @pytest_asyncio.fixture()
     def create_client(self, request: FixtureRequest) -> Callable[..., 
RedisCluster]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_connect.py 
new/redis-5.2.1/tests/test_asyncio/test_connect.py
--- old/redis-5.2.0/tests/test_asyncio/test_connect.py  2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_connect.py  2024-12-06 
10:50:17.000000000 +0100
@@ -11,7 +11,7 @@
 )
 from redis.exceptions import ConnectionError
 
-from ..ssl_utils import get_ssl_filename
+from ..ssl_utils import CertificateType, get_tls_certificates
 
 _CLIENT_NAME = "test-suite-client"
 _CMD_SEP = b"\r\n"
@@ -57,19 +57,21 @@
 )
 async def test_tcp_ssl_tls12_custom_ciphers(tcp_address, ssl_ciphers):
     host, port = tcp_address
-    certfile = get_ssl_filename("client-cert.pem")
-    keyfile = get_ssl_filename("client-key.pem")
-    ca_certfile = get_ssl_filename("ca-cert.pem")
+
+    server_certs = get_tls_certificates(cert_type=CertificateType.server)
+
     conn = SSLConnection(
         host=host,
         port=port,
         client_name=_CLIENT_NAME,
-        ssl_ca_certs=ca_certfile,
+        ssl_ca_certs=server_certs.ca_certfile,
         socket_timeout=10,
         ssl_min_version=ssl.TLSVersion.TLSv1_2,
         ssl_ciphers=ssl_ciphers,
     )
-    await _assert_connect(conn, tcp_address, certfile=certfile, 
keyfile=keyfile)
+    await _assert_connect(
+        conn, tcp_address, certfile=server_certs.certfile, 
keyfile=server_certs.keyfile
+    )
     await conn.disconnect()
 
 
@@ -86,18 +88,20 @@
 )
 async def test_tcp_ssl_connect(tcp_address, ssl_min_version):
     host, port = tcp_address
-    certfile = get_ssl_filename("client-cert.pem")
-    keyfile = get_ssl_filename("client-key.pem")
-    ca_certfile = get_ssl_filename("ca-cert.pem")
+
+    server_certs = get_tls_certificates(cert_type=CertificateType.server)
+
     conn = SSLConnection(
         host=host,
         port=port,
         client_name=_CLIENT_NAME,
-        ssl_ca_certs=ca_certfile,
+        ssl_ca_certs=server_certs.ca_certfile,
         socket_timeout=10,
         ssl_min_version=ssl_min_version,
     )
-    await _assert_connect(conn, tcp_address, certfile=certfile, 
keyfile=keyfile)
+    await _assert_connect(
+        conn, tcp_address, certfile=server_certs.certfile, 
keyfile=server_certs.keyfile
+    )
     await conn.disconnect()
 
 
@@ -105,8 +109,7 @@
 @pytest.mark.skipif(not ssl.HAS_TLSv1_3, reason="requires TLSv1.3")
 async def test_tcp_ssl_version_mismatch(tcp_address):
     host, port = tcp_address
-    certfile = get_ssl_filename("server-cert.pem")
-    keyfile = get_ssl_filename("server-key.pem")
+    certfile, keyfile, _ = 
get_tls_certificates(cert_type=CertificateType.server)
     conn = SSLConnection(
         host=host,
         port=port,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_cwe_404.py 
new/redis-5.2.1/tests/test_asyncio/test_cwe_404.py
--- old/redis-5.2.0/tests/test_asyncio/test_cwe_404.py  2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_cwe_404.py  2024-12-06 
10:50:17.000000000 +0100
@@ -208,7 +208,7 @@
         port = cluster_port + i
         remapped = remap_base + i
         forward_addr = hostname, port
-        proxy = DelayProxy(addr=("127.0.0.1", remapped), 
redis_addr=forward_addr)
+        proxy = DelayProxy(addr=(hostname, remapped), redis_addr=forward_addr)
         proxies.append(proxy)
 
     def all_clear():
@@ -233,7 +233,7 @@
             await stack.enter_async_context(p)
 
         r = RedisCluster.from_url(
-            f"redis://127.0.0.1:{remap_base}", address_remap=remap
+            f"redis://{hostname}:{remap_base}", address_remap=remap
         )
         try:
             await r.initialize()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_graph.py 
new/redis-5.2.1/tests/test_asyncio/test_graph.py
--- old/redis-5.2.0/tests/test_asyncio/test_graph.py    2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_graph.py    2024-12-06 
10:50:17.000000000 +0100
@@ -12,7 +12,7 @@
     return await create_redis(decode_responses=True, 
url="redis://localhost:6480")
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_bulk(decoded_r):
     with pytest.raises(NotImplementedError):
@@ -20,7 +20,7 @@
         await decoded_r.graph().bulk(foo="bar!")
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_graph_creation(decoded_r: redis.Redis):
     graph = decoded_r.graph()
@@ -66,7 +66,7 @@
     await graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_array_functions(decoded_r: redis.Redis):
     graph = decoded_r.graph()
@@ -90,7 +90,7 @@
     assert [a] == result.result_set[0][0]
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_path(decoded_r: redis.Redis):
     node0 = Node(node_id=0, label="L1")
@@ -111,7 +111,7 @@
     assert expected_results == result.result_set
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_param(decoded_r: redis.Redis):
     params = [1, 2.3, "str", True, False, None, [0, 1, 2]]
@@ -122,7 +122,7 @@
         assert expected_results == result.result_set
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_map(decoded_r: redis.Redis):
     query = "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"
@@ -140,7 +140,7 @@
     assert actual == expected
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_point(decoded_r: redis.Redis):
     query = "RETURN point({latitude: 32.070794860, longitude: 34.820751118})"
@@ -158,7 +158,7 @@
     assert abs(actual["longitude"] - expected_lon) < 0.001
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_index_response(decoded_r: redis.Redis):
     result_set = await decoded_r.graph().query("CREATE INDEX ON :person(age)")
@@ -174,7 +174,7 @@
         await decoded_r.graph().query("DROP INDEX ON :person(age)")
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_stringify_query_result(decoded_r: redis.Redis):
     graph = decoded_r.graph()
@@ -229,7 +229,7 @@
     await graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_optional_match(decoded_r: redis.Redis):
     # Build a graph of form (a)-[R]->(b)
@@ -255,7 +255,7 @@
     await graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_cached_execution(decoded_r: redis.Redis):
     await decoded_r.graph().query("CREATE ()")
@@ -276,7 +276,7 @@
     assert cached_result.cached_execution
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_slowlog(decoded_r: redis.Redis):
     create_query = """CREATE
@@ -291,7 +291,7 @@
 
 
 @pytest.mark.xfail(strict=False)
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_query_timeout(decoded_r: redis.Redis):
     # Build a sample graph with 1000 nodes.
@@ -306,7 +306,7 @@
         assert False is False
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_read_only_query(decoded_r: redis.Redis):
     with pytest.raises(Exception):
@@ -316,7 +316,7 @@
         assert False is False
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_profile(decoded_r: redis.Redis):
     q = """UNWIND range(1, 3) AS x CREATE (p:Person {v:x})"""
@@ -333,7 +333,7 @@
 
 
 @skip_if_redis_enterprise()
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_config(decoded_r: redis.Redis):
     config_name = "RESULTSET_SIZE"
@@ -366,7 +366,7 @@
 
 
 @pytest.mark.onlynoncluster
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_list_keys(decoded_r: redis.Redis):
     result = await decoded_r.graph().list_keys()
@@ -390,7 +390,7 @@
     assert result == []
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_multi_label(decoded_r: redis.Redis):
     redis_graph = decoded_r.graph("g")
@@ -417,7 +417,7 @@
         assert True
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_execution_plan(decoded_r: redis.Redis):
     redis_graph = decoded_r.graph("execution_plan")
@@ -437,7 +437,7 @@
     await redis_graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 async def test_explain(decoded_r: redis.Redis):
     redis_graph = decoded_r.graph("execution_plan")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_hash.py 
new/redis-5.2.1/tests/test_asyncio/test_hash.py
--- old/redis-5.2.0/tests/test_asyncio/test_hash.py     2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_hash.py     2024-12-06 
10:50:17.000000000 +0100
@@ -1,4 +1,5 @@
 import asyncio
+import math
 from datetime import datetime, timedelta
 
 from tests.conftest import skip_if_server_version_lt
@@ -128,9 +129,9 @@
 async def test_hexpireat_basic(r):
     await r.delete("test:hash")
     await r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
-    exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
+    exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
     assert await r.hexpireat("test:hash", exp_time, "field1") == [1]
-    await asyncio.sleep(1.1)
+    await asyncio.sleep(2.1)
     assert await r.hexists("test:hash", "field1") is False
     assert await r.hexists("test:hash", "field2") is True
 
@@ -139,9 +140,9 @@
 async def test_hexpireat_with_datetime(r):
     await r.delete("test:hash")
     await r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
-    exp_time = datetime.now() + timedelta(seconds=1)
+    exp_time = (datetime.now() + timedelta(seconds=2)).replace(microsecond=0)
     assert await r.hexpireat("test:hash", exp_time, "field1") == [1]
-    await asyncio.sleep(1.1)
+    await asyncio.sleep(2.1)
     assert await r.hexists("test:hash", "field1") is False
     assert await r.hexists("test:hash", "field2") is True
 
@@ -175,9 +176,9 @@
         "test:hash",
         mapping={"field1": "value1", "field2": "value2", "field3": "value3"},
     )
-    exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
+    exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
     assert await r.hexpireat("test:hash", exp_time, "field1", "field2") == [1, 
1]
-    await asyncio.sleep(1.5)
+    await asyncio.sleep(2.1)
     assert await r.hexists("test:hash", "field1") is False
     assert await r.hexists("test:hash", "field2") is False
     assert await r.hexists("test:hash", "field3") is True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_search.py 
new/redis-5.2.1/tests/test_asyncio/test_search.py
--- old/redis-5.2.0/tests/test_asyncio/test_search.py   2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_search.py   2024-12-06 
10:50:17.000000000 +0100
@@ -1025,6 +1025,8 @@
 
 @pytest.mark.redismod
 @pytest.mark.onlynoncluster
+# NOTE(imalinovskyi): This test contains hardcoded scores valid only for 
RediSearch 2.8+
+@skip_ifmodversion_lt("2.8.0", "search")
 async def test_scorer(decoded_r: redis.Redis):
     await decoded_r.ft().create_index((TextField("description"),))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_sentinel.py 
new/redis-5.2.1/tests/test_asyncio/test_sentinel.py
--- old/redis-5.2.0/tests/test_asyncio/test_sentinel.py 2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_sentinel.py 2024-12-06 
10:50:17.000000000 +0100
@@ -264,3 +264,23 @@
 
     assert calls == 1
     await pool.disconnect()
+
+
[email protected]
+async def test_repr_correctly_represents_connection_object(sentinel):
+    pool = SentinelConnectionPool("mymaster", sentinel)
+    connection = await pool.get_connection("PING")
+
+    assert (
+        str(connection)
+        == 
"<redis.asyncio.sentinel.SentinelManagedConnection,host=127.0.0.1,port=6379)>"  
# noqa: E501
+    )
+    assert connection.connection_pool == pool
+    await pool.release(connection)
+
+    del pool
+
+    assert (
+        str(connection)
+        == 
"<redis.asyncio.sentinel.SentinelManagedConnection,host=127.0.0.1,port=6379)>"  
# noqa: E501
+    )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_asyncio/test_timeseries.py 
new/redis-5.2.1/tests/test_asyncio/test_timeseries.py
--- old/redis-5.2.0/tests/test_asyncio/test_timeseries.py       2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_asyncio/test_timeseries.py       2024-12-06 
10:50:17.000000000 +0100
@@ -765,6 +765,7 @@
         assert compressed_info["memoryUsage"] != 
uncompressed_info["memoryUsage"]
 
 
[email protected]
 @skip_ifmodversion_lt("1.12.0", "timeseries")
 async def test_create_with_insertion_filters(decoded_r: redis.Redis):
     await decoded_r.ts().create(
@@ -788,6 +789,7 @@
     )
 
 
[email protected]
 @skip_ifmodversion_lt("1.12.0", "timeseries")
 async def test_alter_with_insertion_filters(decoded_r: redis.Redis):
     assert 1000 == await decoded_r.ts().add("time-series-1", 1000, 1.0)
@@ -812,6 +814,7 @@
     )
 
 
[email protected]
 @skip_ifmodversion_lt("1.12.0", "timeseries")
 async def test_add_with_insertion_filters(decoded_r: redis.Redis):
     assert 1000 == await decoded_r.ts().add(
@@ -829,6 +832,7 @@
     assert_resp_response(decoded_r, data_points, [(1000, 1.0)], [[1000, 1.0]])
 
 
[email protected]
 @skip_ifmodversion_lt("1.12.0", "timeseries")
 async def test_incrby_with_insertion_filters(decoded_r: redis.Redis):
     assert 1000 == await decoded_r.ts().incrby(
@@ -851,6 +855,7 @@
     assert_resp_response(decoded_r, data_points, [(1000, 11.1)], [[1000, 
11.1]])
 
 
[email protected]
 @skip_ifmodversion_lt("1.12.0", "timeseries")
 async def test_decrby_with_insertion_filters(decoded_r: redis.Redis):
     assert 1000 == await decoded_r.ts().decrby(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_cluster.py 
new/redis-5.2.1/tests/test_cluster.py
--- old/redis-5.2.0/tests/test_cluster.py       2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/tests/test_cluster.py       2024-12-06 10:50:17.000000000 
+0100
@@ -862,21 +862,22 @@
 
     def test_cluster_retry_object(self, r) -> None:
         # Test default retry
+        # FIXME: Workaround for https://github.com/redis/redis-py/issues/3030
+        host = r.get_default_node().host
+
         retry = r.get_connection_kwargs().get("retry")
         assert isinstance(retry, Retry)
         assert retry._retries == 0
         assert isinstance(retry._backoff, type(default_backoff()))
-        node1 = r.get_node("127.0.0.1", 16379).redis_connection
-        node2 = r.get_node("127.0.0.1", 16380).redis_connection
+        node1 = r.get_node(host, 16379).redis_connection
+        node2 = r.get_node(host, 16380).redis_connection
         assert node1.get_retry()._retries == node2.get_retry()._retries
 
         # Test custom retry
         retry = Retry(ExponentialBackoff(10, 5), 5)
-        rc_custom_retry = RedisCluster("127.0.0.1", 16379, retry=retry)
+        rc_custom_retry = RedisCluster(host, 16379, retry=retry)
         assert (
-            rc_custom_retry.get_node("127.0.0.1", 16379)
-            .redis_connection.get_retry()
-            ._retries
+            rc_custom_retry.get_node(host, 
16379).redis_connection.get_retry()._retries
             == retry._retries
         )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_connect.py 
new/redis-5.2.1/tests/test_connect.py
--- old/redis-5.2.0/tests/test_connect.py       2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/tests/test_connect.py       2024-12-06 10:50:17.000000000 
+0100
@@ -8,7 +8,7 @@
 from redis.connection import Connection, SSLConnection, 
UnixDomainSocketConnection
 from redis.exceptions import RedisError
 
-from .ssl_utils import get_ssl_filename
+from .ssl_utils import CertificateType, get_tls_certificates
 
 _CLIENT_NAME = "test-suite-client"
 _CMD_SEP = b"\r\n"
@@ -54,18 +54,18 @@
 )
 def test_tcp_ssl_connect(tcp_address, ssl_min_version):
     host, port = tcp_address
-    certfile = get_ssl_filename("client-cert.pem")
-    keyfile = get_ssl_filename("client-key.pem")
-    ca_certfile = get_ssl_filename("ca-cert.pem")
+    server_certs = get_tls_certificates(cert_type=CertificateType.server)
     conn = SSLConnection(
         host=host,
         port=port,
         client_name=_CLIENT_NAME,
-        ssl_ca_certs=ca_certfile,
+        ssl_ca_certs=server_certs.ca_certfile,
         socket_timeout=10,
         ssl_min_version=ssl_min_version,
     )
-    _assert_connect(conn, tcp_address, certfile=certfile, keyfile=keyfile)
+    _assert_connect(
+        conn, tcp_address, certfile=server_certs.certfile, 
keyfile=server_certs.keyfile
+    )
 
 
 @pytest.mark.ssl
@@ -79,19 +79,21 @@
 )
 def test_tcp_ssl_tls12_custom_ciphers(tcp_address, ssl_ciphers):
     host, port = tcp_address
-    certfile = get_ssl_filename("client-cert.pem")
-    keyfile = get_ssl_filename("client-key.pem")
-    ca_certfile = get_ssl_filename("ca-cert.pem")
+
+    server_certs = get_tls_certificates(cert_type=CertificateType.server)
+
     conn = SSLConnection(
         host=host,
         port=port,
         client_name=_CLIENT_NAME,
-        ssl_ca_certs=ca_certfile,
+        ssl_ca_certs=server_certs.ca_certfile,
         socket_timeout=10,
         ssl_min_version=ssl.TLSVersion.TLSv1_2,
         ssl_ciphers=ssl_ciphers,
     )
-    _assert_connect(conn, tcp_address, certfile=certfile, keyfile=keyfile)
+    _assert_connect(
+        conn, tcp_address, certfile=server_certs.certfile, 
keyfile=server_certs.keyfile
+    )
 
 
 """
@@ -115,8 +117,7 @@
 @pytest.mark.skipif(not ssl.HAS_TLSv1_3, reason="requires TLSv1.3")
 def test_tcp_ssl_version_mismatch(tcp_address):
     host, port = tcp_address
-    certfile = get_ssl_filename("server-cert.pem")
-    keyfile = get_ssl_filename("server-key.pem")
+    certfile, keyfile, _ = 
get_tls_certificates(cert_type=CertificateType.server)
     conn = SSLConnection(
         host=host,
         port=port,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_graph.py 
new/redis-5.2.1/tests/test_graph.py
--- old/redis-5.2.0/tests/test_graph.py 2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_graph.py 2024-12-06 10:50:17.000000000 +0100
@@ -32,7 +32,7 @@
     return r
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_bulk(client):
     with pytest.raises(NotImplementedError):
@@ -40,7 +40,7 @@
         client.graph().bulk(foo="bar!")
 
 
[email protected]
[email protected]
 def test_graph_creation_throws_deprecation_warning(client):
     """Verify that a DeprecationWarning is raised when creating a Graph 
instance."""
 
@@ -49,7 +49,7 @@
         client.graph()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_graph_creation(client):
     graph = client.graph()
@@ -95,7 +95,7 @@
     graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_array_functions(client):
     query = """CREATE (p:person{name:'a',age:32, array:[0,1,2]})"""
@@ -117,7 +117,7 @@
     assert [a] == result.result_set[0][0]
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_path(client):
     node0 = Node(node_id=0, label="L1")
@@ -138,7 +138,7 @@
     assert expected_results == result.result_set
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_param(client):
     params = [1, 2.3, "str", True, False, None, [0, 1, 2], r"\" RETURN 1337 
//"]
@@ -149,7 +149,7 @@
         assert expected_results == result.result_set
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_map(client):
     query = "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}"
@@ -167,7 +167,7 @@
     assert actual == expected
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_point(client):
     query = "RETURN point({latitude: 32.070794860, longitude: 34.820751118})"
@@ -185,7 +185,7 @@
     assert abs(actual["longitude"] - expected_lon) < 0.001
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_index_response(client):
     result_set = client.graph().query("CREATE INDEX ON :person(age)")
@@ -201,7 +201,7 @@
         client.graph().query("DROP INDEX ON :person(age)")
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_stringify_query_result(client):
     graph = client.graph()
@@ -256,7 +256,7 @@
     graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_optional_match(client):
     # Build a graph of form (a)-[R]->(b)
@@ -282,7 +282,7 @@
     graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_cached_execution(client):
     client.graph().query("CREATE ()")
@@ -301,7 +301,7 @@
     assert cached_result.cached_execution
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_slowlog(client):
     create_query = """CREATE (:Rider
@@ -315,7 +315,7 @@
     assert results[0][2] == create_query
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 @pytest.mark.xfail(strict=False)
 def test_query_timeout(client):
@@ -331,7 +331,7 @@
         assert False is False
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_read_only_query(client):
     with pytest.raises(Exception):
@@ -341,7 +341,7 @@
         assert False is False
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_profile(client):
     q = """UNWIND range(1, 3) AS x CREATE (p:Person {v:x})"""
@@ -357,7 +357,7 @@
     assert "Node By Label Scan | (p:Person) | Records produced: 3" in profile
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 @skip_if_redis_enterprise()
 def test_config(client):
@@ -391,7 +391,7 @@
 
 
 @pytest.mark.onlynoncluster
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_list_keys(client):
     result = client.graph().list_keys()
@@ -415,7 +415,7 @@
     assert result == []
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_multi_label(client):
     redis_graph = client.graph("g")
@@ -442,7 +442,7 @@
         assert True
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_cache_sync(client):
     pass
@@ -516,7 +516,7 @@
     assert A._relationship_types[1] == "R"
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_execution_plan(client):
     redis_graph = client.graph("execution_plan")
@@ -536,7 +536,7 @@
     redis_graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_explain(client):
     redis_graph = client.graph("execution_plan")
@@ -626,7 +626,7 @@
     redis_graph.delete()
 
 
[email protected]
[email protected]
 @skip_if_resp_version(3)
 def test_resultset_statistics(client):
     with patch.object(target=QueryResult, attribute="_get_stat") as 
mock_get_stats:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_graph_utils/test_edge.py 
new/redis-5.2.1/tests/test_graph_utils/test_edge.py
--- old/redis-5.2.0/tests/test_graph_utils/test_edge.py 2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_graph_utils/test_edge.py 2024-12-06 
10:50:17.000000000 +0100
@@ -2,7 +2,7 @@
 from redis.commands.graph import edge, node
 
 
[email protected]
[email protected]
 def test_init():
     with pytest.raises(AssertionError):
         edge.Edge(None, None, None)
@@ -14,7 +14,7 @@
     )
 
 
[email protected]
[email protected]
 def test_to_string():
     props_result = edge.Edge(
         node.Node(), None, node.Node(), properties={"a": "a", "b": 10}
@@ -27,7 +27,7 @@
     assert no_props_result == ""
 
 
[email protected]
[email protected]
 def test_stringify():
     john = node.Node(
         alias="a",
@@ -60,7 +60,7 @@
     )
 
 
[email protected]
[email protected]
 def test_comparison():
     node1 = node.Node(node_id=1)
     node2 = node.Node(node_id=2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_graph_utils/test_node.py 
new/redis-5.2.1/tests/test_graph_utils/test_node.py
--- old/redis-5.2.0/tests/test_graph_utils/test_node.py 2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_graph_utils/test_node.py 2024-12-06 
10:50:17.000000000 +0100
@@ -12,7 +12,7 @@
     return no_args, no_props, props_only, no_label, multi_label
 
 
[email protected]
[email protected]
 def test_to_string(fixture):
     no_args, no_props, props_only, no_label, multi_label = fixture
     assert no_args.to_string() == ""
@@ -22,7 +22,7 @@
     assert multi_label.to_string() == ""
 
 
[email protected]
[email protected]
 def test_stringify(fixture):
     no_args, no_props, props_only, no_label, multi_label = fixture
     assert str(no_args) == "()"
@@ -32,7 +32,7 @@
     assert str(multi_label) == "(alias:l:ll)"
 
 
[email protected]
[email protected]
 def test_comparison(fixture):
     no_args, no_props, props_only, no_label, multi_label = fixture
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_graph_utils/test_path.py 
new/redis-5.2.1/tests/test_graph_utils/test_path.py
--- old/redis-5.2.0/tests/test_graph_utils/test_path.py 2024-10-24 
17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_graph_utils/test_path.py 2024-12-06 
10:50:17.000000000 +0100
@@ -2,7 +2,7 @@
 from redis.commands.graph import edge, node, path
 
 
[email protected]
[email protected]
 def test_init():
     with pytest.raises(TypeError):
         path.Path(None, None)
@@ -12,7 +12,7 @@
     assert isinstance(path.Path([], []), path.Path)
 
 
[email protected]
[email protected]
 def test_new_empty_path():
     new_empty_path = path.Path.new_empty_path()
     assert isinstance(new_empty_path, path.Path)
@@ -20,7 +20,7 @@
     assert new_empty_path._edges == []
 
 
[email protected]
[email protected]
 def test_wrong_flows():
     node_1 = node.Node(node_id=1)
     node_2 = node.Node(node_id=2)
@@ -42,7 +42,7 @@
         p.add_edge(edge_2)
 
 
[email protected]
[email protected]
 def test_nodes_and_edges():
     node_1 = node.Node(node_id=1)
     node_2 = node.Node(node_id=2)
@@ -69,7 +69,7 @@
     assert 2 == p.nodes_count()
 
 
[email protected]
[email protected]
 def test_compare():
     node_1 = node.Node(node_id=1)
     node_2 = node.Node(node_id=2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_hash.py 
new/redis-5.2.1/tests/test_hash.py
--- old/redis-5.2.0/tests/test_hash.py  2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_hash.py  2024-12-06 10:50:17.000000000 +0100
@@ -1,3 +1,4 @@
+import math
 import time
 from datetime import datetime, timedelta
 
@@ -147,9 +148,9 @@
 def test_hexpireat_basic(r):
     r.delete("test:hash")
     r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
-    exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
+    exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
     assert r.hexpireat("test:hash", exp_time, "field1") == [1]
-    time.sleep(1.1)
+    time.sleep(2.1)
     assert r.hexists("test:hash", "field1") is False
     assert r.hexists("test:hash", "field2") is True
 
@@ -158,9 +159,9 @@
 def test_hexpireat_with_datetime(r):
     r.delete("test:hash")
     r.hset("test:hash", mapping={"field1": "value1", "field2": "value2"})
-    exp_time = datetime.now() + timedelta(seconds=1)
+    exp_time = (datetime.now() + timedelta(seconds=2)).replace(microsecond=0)
     assert r.hexpireat("test:hash", exp_time, "field1") == [1]
-    time.sleep(1.1)
+    time.sleep(2.1)
     assert r.hexists("test:hash", "field1") is False
     assert r.hexists("test:hash", "field2") is True
 
@@ -194,9 +195,9 @@
         "test:hash",
         mapping={"field1": "value1", "field2": "value2", "field3": "value3"},
     )
-    exp_time = int((datetime.now() + timedelta(seconds=1)).timestamp())
+    exp_time = math.ceil((datetime.now() + timedelta(seconds=1)).timestamp())
     assert r.hexpireat("test:hash", exp_time, "field1", "field2") == [1, 1]
-    time.sleep(1.1)
+    time.sleep(2.1)
     assert r.hexists("test:hash", "field1") is False
     assert r.hexists("test:hash", "field2") is False
     assert r.hexists("test:hash", "field3") is True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_json.py 
new/redis-5.2.1/tests/test_json.py
--- old/redis-5.2.0/tests/test_json.py  2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_json.py  2024-12-06 10:50:17.000000000 +0100
@@ -1521,8 +1521,8 @@
 
     root = tempfile.mkdtemp()
     sub = tempfile.mkdtemp(dir=root)
-    jsonfile = tempfile.mktemp(suffix=".json", dir=sub)
-    nojsonfile = tempfile.mktemp(dir=root)
+    jsonfile = tempfile.mkstemp(suffix=".json", dir=sub)[1]
+    nojsonfile = tempfile.mkstemp(dir=root)[1]
 
     with open(jsonfile, "w+") as fp:
         fp.write(json.dumps({"hello": "world"}))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_search.py 
new/redis-5.2.1/tests/test_search.py
--- old/redis-5.2.0/tests/test_search.py        2024-10-24 17:04:05.000000000 
+0200
+++ new/redis-5.2.1/tests/test_search.py        2024-12-06 10:50:17.000000000 
+0100
@@ -30,6 +30,7 @@
     is_resp2_connection,
     skip_if_redis_enterprise,
     skip_if_resp_version,
+    skip_if_server_version_lt,
     skip_ifmodversion_lt,
 )
 
@@ -932,6 +933,8 @@
 
 @pytest.mark.redismod
 @pytest.mark.onlynoncluster
+# NOTE(imalinovskyi): This test contains hardcoded scores valid only for 
RediSearch 2.8+
+@skip_ifmodversion_lt("2.8.0", "search")
 def test_scorer(client):
     client.ft().create_index((TextField("description"),))
 
@@ -2239,6 +2242,8 @@
 
 
 @pytest.mark.redismod
+@skip_if_server_version_lt("7.4.0")
+@skip_ifmodversion_lt("2.10.0", "search")
 def test_geoshapes_query_intersects_and_disjoint(client):
     client.ft().create_index((GeoShapeField("g", 
coord_system=GeoShapeField.FLAT)))
     client.hset("doc_point1", mapping={"g": "POINT (10 10)"})
@@ -2442,6 +2447,8 @@
 
 
 @pytest.mark.redismod
+@skip_if_server_version_lt("7.2.0")
+@skip_ifmodversion_lt("2.8.4", "search")
 def test_geoshape(client: redis.Redis):
     client.ft().create_index(GeoShapeField("geom", GeoShapeField.FLAT))
     waitForIndex(client, getattr(client.ft(), "index_name", "idx"))
@@ -2458,6 +2465,8 @@
 
 
 @pytest.mark.redismod
+@skip_if_server_version_lt("7.4.0")
+@skip_ifmodversion_lt("2.10.0", "search")
 def test_search_missing_fields(client):
     definition = IndexDefinition(prefix=["property:"], 
index_type=IndexType.HASH)
 
@@ -2525,6 +2534,8 @@
 
 
 @pytest.mark.redismod
+@skip_if_server_version_lt("7.4.0")
+@skip_ifmodversion_lt("2.10.0", "search")
 def test_search_empty_fields(client):
     definition = IndexDefinition(prefix=["property:"], 
index_type=IndexType.HASH)
 
@@ -2596,6 +2607,8 @@
 
 
 @pytest.mark.redismod
+@skip_if_server_version_lt("7.4.0")
+@skip_ifmodversion_lt("2.10.0", "search")
 def test_special_characters_in_fields(client):
     definition = IndexDefinition(prefix=["resource:"], 
index_type=IndexType.HASH)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.2.0/tests/test_ssl.py 
new/redis-5.2.1/tests/test_ssl.py
--- old/redis-5.2.0/tests/test_ssl.py   2024-10-24 17:04:05.000000000 +0200
+++ new/redis-5.2.1/tests/test_ssl.py   2024-12-06 10:50:17.000000000 +0100
@@ -7,7 +7,7 @@
 from redis.exceptions import ConnectionError, RedisError
 
 from .conftest import skip_if_cryptography, skip_if_nocryptography
-from .ssl_utils import get_ssl_filename
+from .ssl_utils import CertificateType, get_tls_certificates
 
 
 @pytest.mark.ssl
@@ -18,10 +18,13 @@
     and connecting to the appropriate port.
     """
 
-    CA_CERT = get_ssl_filename("ca-cert.pem")
-    CLIENT_CERT = get_ssl_filename("client-cert.pem")
-    CLIENT_KEY = get_ssl_filename("client-key.pem")
-    SERVER_CERT = get_ssl_filename("server-cert.pem")
+    @pytest.fixture(autouse=True)
+    def _set_ssl_certs(self, request):
+        tls_cert_subdir = request.session.config.REDIS_INFO["tls_cert_subdir"]
+        self.client_certs = get_tls_certificates(tls_cert_subdir)
+        self.server_certs = get_tls_certificates(
+            tls_cert_subdir, cert_type=CertificateType.server
+        )
 
     def test_ssl_with_invalid_cert(self, request):
         ssl_url = request.config.option.redis_ssl_url
@@ -55,16 +58,16 @@
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.certfile,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
-            ssl_ca_certs=self.CA_CERT,
+            ssl_ca_certs=self.client_certs.ca_certfile,
         )
         assert r.ping()
         r.close()
 
     def test_validating_self_signed_string_certificate(self, request):
-        with open(self.CA_CERT) as f:
+        with open(self.client_certs.ca_certfile) as f:
             cert_data = f.read()
         ssl_url = request.config.option.redis_ssl_url
         p = urlparse(ssl_url)[1].split(":")
@@ -72,8 +75,8 @@
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.certfile,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
             ssl_ca_data=cert_data,
         )
@@ -149,10 +152,10 @@
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.certfile,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
-            ssl_ca_certs=self.CA_CERT,
+            ssl_ca_certs=self.client_certs.ca_certfile,
             ssl_validate_ocsp=True,
         )
         return r
@@ -247,10 +250,10 @@
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.cert,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
-            ssl_ca_certs=self.CA_CERT,
+            ssl_ca_certs=self.client_certs.ca_certfile,
             ssl_validate_ocsp=True,
             ssl_ocsp_context=p,  # just needs to not be none
         )
@@ -260,19 +263,19 @@
         r.close()
 
         ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
-        ctx.use_certificate_file(self.CLIENT_CERT)
-        ctx.use_privatekey_file(self.CLIENT_KEY)
+        ctx.use_certificate_file(self.client_certs.cert)
+        ctx.use_privatekey_file(self.client_certs.keyfile)
 
         r = redis.Redis(
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.cert,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
-            ssl_ca_certs=self.CA_CERT,
+            ssl_ca_certs=self.client_certs.ca_certfile,
             ssl_ocsp_context=ctx,
-            ssl_ocsp_expected_cert=open(self.SERVER_CERT, "rb").read(),
+            ssl_ocsp_expected_cert=open(self.server_certs.ca_certfile, 
"rb").read(),
             ssl_validate_ocsp_stapled=True,
         )
 
@@ -285,10 +288,10 @@
             host=p[0],
             port=p[1],
             ssl=True,
-            ssl_certfile=self.CLIENT_CERT,
-            ssl_keyfile=self.CLIENT_KEY,
+            ssl_certfile=self.client_certs.cert,
+            ssl_keyfile=self.client_certs.keyfile,
             ssl_cert_reqs="required",
-            ssl_ca_certs=self.CA_CERT,
+            ssl_ca_certs=self.client_certs.ca_certfile,
             ssl_validate_ocsp_stapled=True,
         )
 

Reply via email to