diff --git a/CHANGES b/CHANGES index 82c5b6db..8c428be5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,4 @@ + * Add 'redis://' and 'rediss://' protocol support * Update `ResponseT` type hint * Allow to control the minimum SSL version * Add an optional lock_name attribute to LockError. diff --git a/tests/test_asyncio/test_connection_pool.py b/tests/test_asyncio/test_connection_pool.py index ce8d792a..b337f0e1 100644 --- a/tests/test_asyncio/test_connection_pool.py +++ b/tests/test_asyncio/test_connection_pool.py @@ -6,6 +6,8 @@ import valkey.asyncio as valkey from tests.conftest import skip_if_server_version_lt from valkey.asyncio.connection import Connection, to_bool +from valkey.utils import SSL_AVAILABLE + from .compat import aclosing, mock from .conftest import asynccontextmanager @@ -302,32 +304,37 @@ def test_repr_contains_db_info_unix(self): assert expected in repr(pool) +@pytest.mark.parametrize("connection_protocol", ["valkey", "redis"]) class TestConnectionPoolURLParsing: - def test_hostname(self): - pool = valkey.ConnectionPool.from_url("valkey://my.host") + def test_hostname(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://my.host") assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "my.host"} - def test_quoted_hostname(self): - pool = valkey.ConnectionPool.from_url("valkey://my %2F host %2B%3D+") + def test_quoted_hostname(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://my %2F host %2B%3D+" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "my / host +=+"} - def test_port(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost:6380") + def test_port(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://localhost:6380") assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "port": 6380} @skip_if_server_version_lt("6.0.0") - def test_username(self): - pool = valkey.ConnectionPool.from_url("valkey://myuser:@localhost") + def test_username(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://myuser:@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "username": "myuser"} @skip_if_server_version_lt("6.0.0") - def test_quoted_username(self): + def test_quoted_username(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://%2Fmyuser%2F%2B name%3D%24+:@localhost" + f"{connection_protocol}://%2Fmyuser%2F%2B name%3D%24+:@localhost" ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { @@ -335,14 +342,16 @@ def test_quoted_username(self): "username": "/myuser/+ name=$+", } - def test_password(self): - pool = valkey.ConnectionPool.from_url("valkey://:mypassword@localhost") + def test_password(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://:mypassword@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "password": "mypassword"} - def test_quoted_password(self): + def test_quoted_password(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://:%2Fmypass%2F%2B word%3D%24+@localhost" + f"{connection_protocol}://:%2Fmypass%2F%2B word%3D%24+@localhost" ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { @@ -351,8 +360,10 @@ def test_quoted_password(self): } @skip_if_server_version_lt("6.0.0") - def test_username_and_password(self): - pool = valkey.ConnectionPool.from_url("valkey://myuser:mypass@localhost") + def test_username_and_password(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://myuser:mypass@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { "host": "localhost", @@ -360,24 +371,30 @@ def test_username_and_password(self): "password": "mypass", } - def test_db_as_argument(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost", db=1) + def test_db_as_argument(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 1} - def test_db_in_path(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost/2", db=1) + def test_db_in_path(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost/2", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 2} - def test_db_in_querystring(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost/2?db=3", db=1) + def test_db_in_querystring(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost/2?db=3", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 3} - def test_extra_typed_querystring_options(self): + def test_extra_typed_querystring_options(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://localhost/2?socket_timeout=20&socket_connect_timeout=10" + f"{connection_protocol}://localhost/2?socket_timeout=20&socket_connect_timeout=10" "&socket_keepalive=&retry_on_timeout=Yes&max_connections=10" ) @@ -391,59 +408,65 @@ def test_extra_typed_querystring_options(self): } assert pool.max_connections == 10 - def test_boolean_parsing(self): - for expected, value in ( - (None, None), - (None, ""), - (False, 0), - (False, "0"), - (False, "f"), - (False, "F"), - (False, "False"), - (False, "n"), - (False, "N"), - (False, "No"), - (True, 1), - (True, "1"), - (True, "y"), - (True, "Y"), - (True, "Yes"), - ): - assert expected is to_bool(value) - - def test_client_name_in_querystring(self): + def test_client_name_in_querystring(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://location?client_name=test-client" + f"{connection_protocol}://location?client_name=test-client" ) assert pool.connection_kwargs["client_name"] == "test-client" - def test_invalid_extra_typed_querystring_options(self): + def test_invalid_extra_typed_querystring_options(self, connection_protocol): with pytest.raises(ValueError): valkey.ConnectionPool.from_url( - "valkey://localhost/2?socket_timeout=_&socket_connect_timeout=abc" + f"{connection_protocol}://localhost/2?socket_timeout=_&socket_connect_timeout=abc" ) - def test_extra_querystring_options(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost?a=1&b=2") + def test_extra_querystring_options(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost?a=1&b=2" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "a": "1", "b": "2"} - def test_calling_from_subclass_returns_correct_instance(self): - pool = valkey.BlockingConnectionPool.from_url("valkey://localhost") + def test_calling_from_subclass_returns_correct_instance(self, connection_protocol): + pool = valkey.BlockingConnectionPool.from_url( + f"{connection_protocol}://localhost" + ) assert isinstance(pool, valkey.BlockingConnectionPool) - def test_client_creates_connection_pool(self): - r = valkey.Valkey.from_url("valkey://myhost") + def test_client_creates_connection_pool(self, connection_protocol): + r = valkey.Valkey.from_url(f"{connection_protocol}://myhost") assert r.connection_pool.connection_class == valkey.Connection assert r.connection_pool.connection_kwargs == {"host": "myhost"} - def test_invalid_scheme_raises_error(self): - with pytest.raises(ValueError) as cm: - valkey.ConnectionPool.from_url("localhost") - assert str(cm.value) == ( - "Valkey URL must specify one of the following schemes " - "(valkey://, valkeys://, unix://)" - ) + +def test_invalid_scheme_raises_error(): + with pytest.raises(ValueError) as cm: + valkey.ConnectionPool.from_url("localhost") + assert str(cm.value) == ( + "Valkey URL must specify one of the following schemes " + "(valkey://, valkeys://, redis://, rediss://, unix://)" + ) + + +def test_boolean_parsing(): + for expected, value in ( + (None, None), + (None, ""), + (False, 0), + (False, "0"), + (False, "f"), + (False, "F"), + (False, "False"), + (False, "n"), + (False, "N"), + (False, "No"), + (True, 1), + (True, "1"), + (True, "y"), + (True, "Y"), + (True, "Yes"), + ): + assert expected is to_bool(value) class TestBlockingConnectionPoolURLParsing: @@ -541,32 +564,44 @@ def test_extra_querystring_options(self): assert pool.connection_kwargs == {"path": "/socket", "a": "1", "b": "2"} +@pytest.mark.skipif(not SSL_AVAILABLE, reason="SSL not installed") +@pytest.mark.parametrize("connection_protocol", ["valkeys", "rediss"]) class TestSSLConnectionURLParsing: - def test_host(self): - pool = valkey.ConnectionPool.from_url("valkeys://my.host") + def test_host(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://my.host") assert pool.connection_class == valkey.SSLConnection assert pool.connection_kwargs == {"host": "my.host"} - def test_cert_reqs_options(self): + def test_cert_reqs_options(self, connection_protocol): import ssl class DummyConnectionPool(valkey.ConnectionPool): def get_connection(self, *args, **kwargs): return self.make_connection() - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=none") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=none" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_NONE - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=optional") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=optional" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_OPTIONAL - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=required") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=required" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_REQUIRED - pool = DummyConnectionPool.from_url("valkeys://?ssl_check_hostname=False") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_check_hostname=False" + ) assert pool.get_connection("_").check_hostname is False - pool = DummyConnectionPool.from_url("valkeys://?ssl_check_hostname=True") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_check_hostname=True" + ) assert pool.get_connection("_").check_hostname is True diff --git a/tests/test_connection_pool.py b/tests/test_connection_pool.py index 07806fa7..bc4ce5cd 100644 --- a/tests/test_connection_pool.py +++ b/tests/test_connection_pool.py @@ -197,32 +197,37 @@ def test_repr_contains_db_info_unix(self): assert expected in repr(pool) +@pytest.mark.parametrize("connection_protocol", ["valkey", "redis"]) class TestConnectionPoolURLParsing: - def test_hostname(self): - pool = valkey.ConnectionPool.from_url("valkey://my.host") + def test_hostname(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://my.host") assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "my.host"} - def test_quoted_hostname(self): - pool = valkey.ConnectionPool.from_url("valkey://my %2F host %2B%3D+") + def test_quoted_hostname(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://my %2F host %2B%3D+" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "my / host +=+"} - def test_port(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost:6380") + def test_port(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://localhost:6380") assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "port": 6380} @skip_if_server_version_lt("6.0.0") - def test_username(self): - pool = valkey.ConnectionPool.from_url("valkey://myuser:@localhost") + def test_username(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://myuser:@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "username": "myuser"} @skip_if_server_version_lt("6.0.0") - def test_quoted_username(self): + def test_quoted_username(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://%2Fmyuser%2F%2B name%3D%24+:@localhost" + f"{connection_protocol}://%2Fmyuser%2F%2B name%3D%24+:@localhost" ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { @@ -230,14 +235,16 @@ def test_quoted_username(self): "username": "/myuser/+ name=$+", } - def test_password(self): - pool = valkey.ConnectionPool.from_url("valkey://:mypassword@localhost") + def test_password(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://:mypassword@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "password": "mypassword"} - def test_quoted_password(self): + def test_quoted_password(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://:%2Fmypass%2F%2B word%3D%24+@localhost" + f"{connection_protocol}://:%2Fmypass%2F%2B word%3D%24+@localhost" ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { @@ -246,8 +253,10 @@ def test_quoted_password(self): } @skip_if_server_version_lt("6.0.0") - def test_username_and_password(self): - pool = valkey.ConnectionPool.from_url("valkey://myuser:mypass@localhost") + def test_username_and_password(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://myuser:mypass@localhost" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == { "host": "localhost", @@ -255,24 +264,30 @@ def test_username_and_password(self): "password": "mypass", } - def test_db_as_argument(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost", db=1) + def test_db_as_argument(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 1} - def test_db_in_path(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost/2", db=1) + def test_db_in_path(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost/2", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 2} - def test_db_in_querystring(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost/2?db=3", db=1) + def test_db_in_querystring(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost/2?db=3", db=1 + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "db": 3} - def test_extra_typed_querystring_options(self): + def test_extra_typed_querystring_options(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://localhost/2?socket_timeout=20&socket_connect_timeout=10" + f"{connection_protocol}://localhost/2?socket_timeout=20&socket_connect_timeout=10" "&socket_keepalive=&retry_on_timeout=Yes&max_connections=10" ) @@ -286,67 +301,54 @@ def test_extra_typed_querystring_options(self): } assert pool.max_connections == 10 - def test_boolean_parsing(self): - for expected, value in ( - (None, None), - (None, ""), - (False, 0), - (False, "0"), - (False, "f"), - (False, "F"), - (False, "False"), - (False, "n"), - (False, "N"), - (False, "No"), - (True, 1), - (True, "1"), - (True, "y"), - (True, "Y"), - (True, "Yes"), - ): - assert expected is to_bool(value) - - def test_client_name_in_querystring(self): + def test_client_name_in_querystring(self, connection_protocol): pool = valkey.ConnectionPool.from_url( - "valkey://location?client_name=test-client" + f"{connection_protocol}://location?client_name=test-client" ) assert pool.connection_kwargs["client_name"] == "test-client" - def test_invalid_extra_typed_querystring_options(self): + def test_invalid_extra_typed_querystring_options(self, connection_protocol): with pytest.raises(ValueError): valkey.ConnectionPool.from_url( - "valkey://localhost/2?socket_timeout=_&socket_connect_timeout=abc" + f"{connection_protocol}://localhost/2?socket_timeout=_&socket_connect_timeout=abc" ) - def test_extra_querystring_options(self): - pool = valkey.ConnectionPool.from_url("valkey://localhost?a=1&b=2") + def test_extra_querystring_options(self, connection_protocol): + pool = valkey.ConnectionPool.from_url( + f"{connection_protocol}://localhost?a=1&b=2" + ) assert pool.connection_class == valkey.Connection assert pool.connection_kwargs == {"host": "localhost", "a": "1", "b": "2"} - def test_calling_from_subclass_returns_correct_instance(self): + def test_calling_from_subclass_returns_correct_instance(self, connection_protocol): pool = valkey.BlockingConnectionPool.from_url("valkey://localhost") assert isinstance(pool, valkey.BlockingConnectionPool) - def test_client_creates_connection_pool(self): - r = valkey.Valkey.from_url("valkey://myhost") + def test_client_creates_connection_pool(self, connection_protocol): + r = valkey.Valkey.from_url(f"{connection_protocol}://myhost") assert r.connection_pool.connection_class == valkey.Connection assert r.connection_pool.connection_kwargs == {"host": "myhost"} - def test_invalid_scheme_raises_error(self): - with pytest.raises(ValueError) as cm: - valkey.ConnectionPool.from_url("localhost") - assert str(cm.value) == ( - "Valkey URL must specify one of the following schemes " - "(valkey://, valkeys://, unix://)" - ) - def test_invalid_scheme_raises_error_when_double_slash_missing(self): - with pytest.raises(ValueError) as cm: - valkey.ConnectionPool.from_url("valkey:foo.bar.com:12345") - assert str(cm.value) == ( - "Valkey URL must specify one of the following schemes " - "(valkey://, valkeys://, unix://)" - ) +def test_boolean_parsing(): + for expected, value in ( + (None, None), + (None, ""), + (False, 0), + (False, "0"), + (False, "f"), + (False, "F"), + (False, "False"), + (False, "n"), + (False, "N"), + (False, "No"), + (True, 1), + (True, "1"), + (True, "y"), + (True, "Y"), + (True, "Yes"), + ): + assert expected is to_bool(value) class TestBlockingConnectionPoolURLParsing: @@ -454,41 +456,52 @@ class MyConnection(valkey.UnixDomainSocketConnection): @pytest.mark.skipif(not SSL_AVAILABLE, reason="SSL not installed") +@pytest.mark.parametrize("connection_protocol", ["valkeys", "rediss"]) class TestSSLConnectionURLParsing: - def test_host(self): - pool = valkey.ConnectionPool.from_url("valkeys://my.host") + def test_host(self, connection_protocol): + pool = valkey.ConnectionPool.from_url(f"{connection_protocol}://my.host") assert pool.connection_class == valkey.SSLConnection assert pool.connection_kwargs == {"host": "my.host"} - def test_connection_class_override(self): + def test_connection_class_override(self, connection_protocol): class MyConnection(valkey.SSLConnection): pass pool = valkey.ConnectionPool.from_url( - "valkeys://my.host", connection_class=MyConnection + f"{connection_protocol}://my.host", connection_class=MyConnection ) assert pool.connection_class == MyConnection - def test_cert_reqs_options(self): + def test_cert_reqs_options(self, connection_protocol): import ssl class DummyConnectionPool(valkey.ConnectionPool): def get_connection(self, *args, **kwargs): return self.make_connection() - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=none") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=none" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_NONE - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=optional") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=optional" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_OPTIONAL - pool = DummyConnectionPool.from_url("valkeys://?ssl_cert_reqs=required") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_cert_reqs=required" + ) assert pool.get_connection("_").cert_reqs == ssl.CERT_REQUIRED - pool = DummyConnectionPool.from_url("valkeys://?ssl_check_hostname=False") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_check_hostname=False" + ) assert pool.get_connection("_").check_hostname is False - pool = DummyConnectionPool.from_url("valkeys://?ssl_check_hostname=True") + pool = DummyConnectionPool.from_url( + f"{connection_protocol}://?ssl_check_hostname=True" + ) assert pool.get_connection("_").check_hostname is True diff --git a/valkey/asyncio/connection.py b/valkey/asyncio/connection.py index 77b329a8..17b76eea 100644 --- a/valkey/asyncio/connection.py +++ b/valkey/asyncio/connection.py @@ -1043,13 +1043,13 @@ def parse_url(url: str) -> ConnectKwargs: if parsed.password: kwargs["password"] = unquote(parsed.password) - # We only support valkey://, valkeys:// and unix:// schemes. + # We only support valkey://, valkeys://, redis://, rediss://, and unix:// schemes. if parsed.scheme == "unix": if parsed.path: kwargs["path"] = unquote(parsed.path) kwargs["connection_class"] = UnixDomainSocketConnection - elif parsed.scheme in ("valkey", "valkeys"): + elif parsed.scheme in ("valkey", "valkeys", "redis", "rediss"): if parsed.hostname: kwargs["host"] = unquote(parsed.hostname) if parsed.port: @@ -1063,10 +1063,11 @@ def parse_url(url: str) -> ConnectKwargs: except (AttributeError, ValueError): pass - if parsed.scheme == "valkeys": + if parsed.scheme in ("valkeys", "rediss"): kwargs["connection_class"] = SSLConnection + else: - valid_schemes = "valkey://, valkeys://, unix://" + valid_schemes = "valkey://, valkeys://, redis://, rediss://, unix://" raise ValueError( f"Valkey URL must specify one of the following schemes ({valid_schemes})" ) diff --git a/valkey/connection.py b/valkey/connection.py index 29d3fbb0..c51e9327 100644 --- a/valkey/connection.py +++ b/valkey/connection.py @@ -971,15 +971,6 @@ def to_bool(value): def parse_url(url): - if not ( - url.startswith("valkey://") - or url.startswith("valkeys://") - or url.startswith("unix://") - ): - raise ValueError( - "Valkey URL must specify one of the following " - "schemes (valkey://, valkeys://, unix://)" - ) url = urlparse(url) kwargs = {} @@ -1001,13 +992,13 @@ def parse_url(url): if url.password: kwargs["password"] = unquote(url.password) - # We only support valkey://, valkeys:// and unix:// schemes. + # We only support valkey://, valkeys://, redis://, rediss://, and unix:// schemes. if url.scheme == "unix": if url.path: kwargs["path"] = unquote(url.path) kwargs["connection_class"] = UnixDomainSocketConnection - else: # implied: url.scheme in ("valkey", "valkeys"): + else: # implied: url.scheme in ("valkey", "valkeys", "redis", "rediss"): if url.hostname: kwargs["host"] = unquote(url.hostname) if url.port: @@ -1021,7 +1012,7 @@ def parse_url(url): except (AttributeError, ValueError): pass - if url.scheme == "valkeys": + if url.scheme in ("valkeys", "rediss"): kwargs["connection_class"] = SSLConnection return kwargs @@ -1050,12 +1041,14 @@ def from_url(cls, url, **kwargs): valkey://[[username]:[password]]@localhost:6379/0 valkeys://[[username]:[password]]@localhost:6379/0 + redis://[[username]:[password]]@localhost:6379/0 + rediss://[[username]:[password]]@localhost:6379/0 unix://[username@]/path/to/socket.sock?db=0[&password=password] Three URL schemes are supported: - - `valkey://` creates a TCP socket connection. - - `valkeys://` creates a SSL wrapped TCP socket connection. + - `valkey://` and `redis://` creates a TCP socket connection. + - `valkeys://` and `rediss://` creates a SSL wrapped TCP socket connection. - ``unix://``: creates a Unix Domain Socket connection. The username, password, hostname, path and all querystring values @@ -1066,7 +1059,7 @@ def from_url(cls, url, **kwargs): found will be used: 1. A ``db`` querystring option, e.g. valkey://localhost?db=0 - 2. If using the valkey:// or valkeys:// schemes, the path argument + 2. If using the valkey://, valkeys://, redis://, or rediss:// schemes, the path argument of the url, e.g. valkey://localhost/0 3. A ``db`` keyword argument to this function.