Repository: redis/redis-py
Pull request #3653 (2025-05-22 13:14:23)

fix: avoid instantiating a connection on _repr__
### Pull Request check-list

_Please make sure to review and check all of these items:_

- [ ] Do tests and lints pass with this change?
- [ ] Do the CI tests pass with this change (enable it first in your forked repo and wait for the github action build to finish)?
- [ ] Is the new or changed code fully tested?
- [ ] Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?
- [ ] Is there an example added to the examples folder (if applicable)?

_NOTE: these things are not required to open a PR and can be done
afterwards / while the PR is open._

### Description of change

Changing the `__repr__` methods in connection pool classes to avoid instantiating a connection object just to have its string representation.


Patch:
diff --git a/redis/asyncio/connection.py b/redis/asyncio/connection.py
index 326daaa8..95390bd6 100644
--- a/redis/asyncio/connection.py
+++ b/redis/asyncio/connection.py
@@ -1112,9 +1112,11 @@ class ConnectionPool:
             self._event_dispatcher = EventDispatcher()
 
     def __repr__(self):
+        conn_kwargs = ",".join([f"{k}={v}" for k, v in self.connection_kwargs.items()])
         return (
             f"<{self.__class__.__module__}.{self.__class__.__name__}"
-            f"({self.connection_class(**self.connection_kwargs)!r})>"
+            f"(<{self.connection_class.__module__}.{self.connection_class.__name__}"
+            f"({conn_kwargs})>)>"
         )
 
     def reset(self):
diff --git a/redis/connection.py b/redis/connection.py
index e87e7976..131ae68c 100644
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -1432,10 +1432,12 @@ class ConnectionPool:
 
         self.reset()
 
-    def __repr__(self) -> (str, str):
+    def __repr__(self) -> str:
+        conn_kwargs = ",".join([f"{k}={v}" for k, v in self.connection_kwargs.items()])
         return (
-            f"<{type(self).__module__}.{type(self).__name__}"
-            f"({repr(self.connection_class(**self.connection_kwargs))})>"
+            f"<{self.__class__.__module__}.{self.__class__.__name__}"
+            f"(<{self.connection_class.__module__}.{self.connection_class.__name__}"
+            f"({conn_kwargs})>)>"
         )
 
     def get_protocol(self):


Test patch:
diff --git a/tests/test_asyncio/test_connection_pool.py b/tests/test_asyncio/test_connection_pool.py
index 09409e04..d0164838 100644
--- a/tests/test_asyncio/test_connection_pool.py
+++ b/tests/test_asyncio/test_connection_pool.py
@@ -294,13 +294,14 @@ class TestBlockingConnectionPool:
         pool = redis.ConnectionPool(
             host="localhost", port=6379, client_name="test-client"
         )
-        expected = "host=localhost,port=6379,db=0,client_name=test-client"
+        expected = "host=localhost,port=6379,client_name=test-client"
         assert expected in repr(pool)
 
     def test_repr_contains_db_info_unix(self):
         pool = redis.ConnectionPool(
             connection_class=redis.UnixDomainSocketConnection,
             path="abc",
+            db=0,
             client_name="test-client",
         )
         expected = "path=abc,db=0,client_name=test-client"
@@ -651,7 +652,7 @@ class TestConnection:
             await r.execute_command("DEBUG", "ERROR", "OOM blah blah")
 
     def test_connect_from_url_tcp(self):
-        connection = redis.Redis.from_url("redis://localhost")
+        connection = redis.Redis.from_url("redis://localhost:6379?db=0")
         pool = connection.connection_pool
 
         assert re.match(
@@ -659,7 +660,7 @@ class TestConnection:
         ).groups() == (
             "ConnectionPool",
             "Connection",
-            "host=localhost,port=6379,db=0",
+            "db=0,host=localhost,port=6379",
         )
 
     def test_connect_from_url_unix(self):
@@ -671,7 +672,7 @@ class TestConnection:
         ).groups() == (
             "ConnectionPool",
             "UnixDomainSocketConnection",
-            "path=/path/to/socket,db=0",
+            "path=/path/to/socket",
         )
 
     @skip_if_redis_enterprise()
diff --git a/tests/test_connection_pool.py b/tests/test_connection_pool.py
index 9e67659f..67b2fd50 100644
--- a/tests/test_connection_pool.py
+++ b/tests/test_connection_pool.py
@@ -205,13 +205,14 @@ class TestBlockingConnectionPool:
         pool = redis.ConnectionPool(
             host="localhost", port=6379, client_name="test-client"
         )
-        expected = "host=localhost,port=6379,db=0,client_name=test-client"
+        expected = "host=localhost,port=6379,client_name=test-client"
         assert expected in repr(pool)
 
     def test_repr_contains_db_info_unix(self):
         pool = redis.ConnectionPool(
             connection_class=redis.UnixDomainSocketConnection,
             path="abc",
+            db=0,
             client_name="test-client",
         )
         expected = "path=abc,db=0,client_name=test-client"
@@ -598,7 +599,7 @@ class TestConnection:
             r.execute_command("DEBUG", "ERROR", "OOM blah blah")
 
     def test_connect_from_url_tcp(self):
-        connection = redis.Redis.from_url("redis://localhost")
+        connection = redis.Redis.from_url("redis://localhost:6379?db=0")
         pool = connection.connection_pool
 
         assert re.match(
@@ -606,7 +607,7 @@ class TestConnection:
         ).groups() == (
             "ConnectionPool",
             "Connection",
-            "host=localhost,port=6379,db=0",
+            "db=0,host=localhost,port=6379",
         )
 
     def test_connect_from_url_unix(self):
@@ -618,7 +619,7 @@ class TestConnection:
         ).groups() == (
             "ConnectionPool",
             "UnixDomainSocketConnection",
-            "path=/path/to/socket,db=0",
+            "path=/path/to/socket",
         )
 
     @skip_if_redis_enterprise()