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, )
