internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: redis/redis-py

Issue:
'UnixDomainSocketConnection' object has no attribute 'socket_timeout'
Caused by the refactoring in https://github.com/redis/redis-py/pull/2588. I'll make a PR to fix it.

```
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/ewoksutils/logging_utils/connection.py", line 73, in emit
    self._send_serialized_record(s)
  File "/builds/workflow/ewoks/ewoksjob/src/ewoksjob/events/handlers/redis.py", line 49, in _send_serialized_record
    n = self._connection.incrby("ewoks_events_count")
  File "/usr/local/lib/python3.7/site-packages/redis/commands/core.py", line 1914, in incrby
    return self.execute_command("INCRBY", name, amount)
  File "/usr/local/lib/python3.7/site-packages/redis/client.py", line 1255, in execute_command
    conn = self.connection or pool.get_connection(command_name, **options)
  File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1441, in get_connection
    connection.connect()
  File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 699, in connect
    lambda: self._connect(), lambda error: self.disconnect(error)
  File "/usr/local/lib/python3.7/site-packages/redis/retry.py", line 46, in call_with_retry
    return do()
  File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 699, in <lambda>
    lambda: self._connect(), lambda error: self.disconnect(error)
  File "/usr/local/lib/python3.7/site-packages/redis/connection.py", line 1171, in _connect
    sock.settimeout(self.socket_timeout)
AttributeError: 'UnixDomainSocketConnection' object has no attribute 'socket_timeout'
```


Discussion:
Thanks @woutdenolf ... I won't lie, as a Star Wars fan, I loved everything ewok releated here :D

Resolving patch:
diff --git a/redis/connection.py b/redis/connection.py
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -1155,8 +1155,9 @@ def _connect(self):
 class UnixDomainSocketConnection(AbstractConnection):
     "Manages UDS communication to and from a Redis server"
 
-    def __init__(self, path="", **kwargs):
+    def __init__(self, path="", socket_timeout=None, **kwargs):
         self.path = path
+        self.socket_timeout = socket_timeout
         super().__init__(**kwargs)
 
     def repr_pieces(self):


Test patch:
Repository: redis/redis-py

Issue:
PytestUnraisableExceptionWarning from asycio client
**Version**: What redis-py and what redis version is the issue happening on?
```txt
redis-py 4.3.4 and 4.5.3
redis 7.0.9
```
**Platform**: What platform / version? (For example Python 3.5.1 on Windows 7 / Ubuntu 15.10 / Azure)
```txt
Python 3.9.16 | packaged by conda-forge
[Clang 14.0.6 ] on darwin 
```
Occurs in both arm64 and Rosetta amd64 environments.

**Description**: Description of your issue, stack traces from errors and code that reproduces the issue

When running unit tests on a redis.asyncio.Redis object, I notice I keep getting `PytestUnraisableExceptionWarning` that is raised because of __del__() calling self.close() in Redis class, as the self.connection attribute was not set due to early failure in the Redis() constructor.

```log
  /Users/me/mambaforge/envs/x86_ds_utils/lib/python3.9/site-packages/_pytest/unraisableexception.py:78: PytestUnraisableExceptionWarning: Exception ignored in: <function Redis.__del__ at 0x17c0919d0>
  
  Traceback (most recent call last):
    File "/Users/me/mambaforge/envs/x86_ds_utils/lib/python3.9/site-packages/redis/asyncio/client.py", line 458, in __del__
      if self.connection is not None:
  AttributeError: 'RedisCache' object has no attribute 'connection'
  
    warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
```

I think this was fixed in the standard (non-async) Redis in #1458 


Discussion:

Resolving patch:
diff --git a/redis/asyncio/client.py b/redis/asyncio/client.py
--- a/redis/asyncio/client.py
+++ b/redis/asyncio/client.py
@@ -702,6 +702,11 @@ async def reset(self):
             self.pending_unsubscribe_patterns = set()
 
     def close(self) -> Awaitable[NoReturn]:
+        # In case a connection property does not yet exist
+        # (due to a crash earlier in the Redis() constructor), return
+        # immediately as there is nothing to clean-up.
+        if not hasattr(self, "connection"):
+            return
         return self.reset()
 
     async def on_connect(self, connection: Connection):


Test patch:
Repository: redis/redis-py

Issue:
Support ZREVRANK: Added the optional `WITHSCORE` argument.
Documented [here](https://redis.io/commands/ZREVRANK).


Discussion:

Resolving patch:
diff --git a/redis/commands/core.py b/redis/commands/core.py
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -4693,13 +4693,22 @@ def zremrangebyscore(
         """
         return self.execute_command("ZREMRANGEBYSCORE", name, min, max)
 
-    def zrevrank(self, name: KeyT, value: EncodableT) -> ResponseT:
+    def zrevrank(
+        self,
+        name: KeyT,
+        value: EncodableT,
+        withscore: bool = False,
+    ) -> ResponseT:
         """
         Returns a 0-based value indicating the descending rank of
-        ``value`` in sorted set ``name``
+        ``value`` in sorted set ``name``.
+        The optional ``withscore`` argument supplements the command's
+        reply with the score of the element returned.
 
         For more information see https://redis.io/commands/zrevrank
         """
+        if withscore:
+            return self.execute_command("ZREVRANK", name, value, "WITHSCORE")
         return self.execute_command("ZREVRANK", name, value)
 
     def zscore(self, name: KeyT, value: EncodableT) -> ResponseT:


Test patch:
diff --git a/tests/test_asyncio/test_commands.py b/tests/test_asyncio/test_commands.py
--- a/tests/test_asyncio/test_commands.py
+++ b/tests/test_asyncio/test_commands.py
@@ -1710,6 +1710,15 @@ async def test_zrevrank(self, r: redis.Redis):
         assert await r.zrevrank("a", "a2") == 3
         assert await r.zrevrank("a", "a6") is None
 
+    @skip_if_server_version_lt("7.2.0")
+    async def test_zrevrank_withscore(self, r: redis.Redis):
+        await r.zadd("a", {"a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5})
+        assert await r.zrevrank("a", "a1") == 4
+        assert await r.zrevrank("a", "a2") == 3
+        assert await r.zrevrank("a", "a6") is None
+        assert await r.zrevrank("a", "a3", withscore=True) == [2, "3"]
+        assert await r.zrevrank("a", "a6", withscore=True) is None
+
     async def test_zscore(self, r: redis.Redis):
         await r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
         assert await r.zscore("a", "a1") == 1.0
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -2641,6 +2641,15 @@ def test_zrevrank(self, r):
         assert r.zrevrank("a", "a2") == 3
         assert r.zrevrank("a", "a6") is None
 
+    @skip_if_server_version_lt("7.2.0")
+    def test_zrevrank_withscore(self, r):
+        r.zadd("a", {"a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5})
+        assert r.zrevrank("a", "a1") == 4
+        assert r.zrevrank("a", "a2") == 3
+        assert r.zrevrank("a", "a6") is None
+        assert r.zrevrank("a", "a3", withscore=True) == [2, "3"]
+        assert r.zrevrank("a", "a6", withscore=True) is None
+
     def test_zscore(self, r):
         r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
         assert r.zscore("a", "a1") == 1.0
Repository: redis/redis-py

Issue:
PytestUnraisableExceptionWarning from asycio client
**Version**: What redis-py and what redis version is the issue happening on?
```txt
redis-py 4.3.4, 4.5.3, 4.5.4
redis 7.0.9
```
**Platform**: What platform / version? (For example Python 3.5.1 on Windows 7 / Ubuntu 15.10 / Azure)
```txt
Python 3.9.16 | packaged by conda-forge
[Clang 14.0.6 ] on darwin 
```
Occurs in both arm64 and Rosetta amd64 environments.

**Description**: Description of your issue, stack traces from errors and code that reproduces the issue

When running unit tests on a redis.asyncio.Redis object, I notice I keep getting `PytestUnraisableExceptionWarning` that is raised because of Redis.__del__(), as the self.connection attribute was not set due to early failure in the Redis() constructor.

```log
  /Users/me/mambaforge/envs/x86_ds_utils/lib/python3.9/site-packages/_pytest/unraisableexception.py:78: PytestUnraisableExceptionWarning: Exception ignored in: <function Redis.__del__ at 0x17c0919d0>
  
  Traceback (most recent call last):
    File "/Users/me/mambaforge/envs/x86_ds_utils/lib/python3.9/site-packages/redis/asyncio/client.py", line 458, in __del__
      if self.connection is not None:
  AttributeError: 'RedisCache' object has no attribute 'connection'
  
    warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))
```

This is the same issue as #2660; the fix #2669 did not resolve this particular AttributeError.
The issue is in `Redis.__del__()` around line 458, where self.connection is not initialized.


Discussion:
I have solved this locally by changing the `Redis.__del__()` method to be:

```py
class Redis:
    # ...
    def __del__(self, _warnings: Any = warnings) -> None:
        if hasattr(self, "connection") and (self.connection is not None):
            _warnings.warn(
                f"Unclosed client session {self!r}", ResourceWarning, source=self
            )
            context = {"client": self, "message": self._DEL_MESSAGE}
            asyncio.get_running_loop().call_exception_handler(context)

```

I have not opened a PR because I am uncertain if this will cause unintended downstream consequences.

Resolving patch:
diff --git a/redis/asyncio/client.py b/redis/asyncio/client.py
--- a/redis/asyncio/client.py
+++ b/redis/asyncio/client.py
@@ -455,7 +455,7 @@ async def __aexit__(self, exc_type, exc_value, traceback):
     _DEL_MESSAGE = "Unclosed Redis client"
 
     def __del__(self, _warnings: Any = warnings) -> None:
-        if self.connection is not None:
+        if hasattr(self, "connection") and (self.connection is not None):
             _warnings.warn(
                 f"Unclosed client session {self!r}", ResourceWarning, source=self
             )


Test patch:
Repository: redis/redis-py

Issue:
HGETALL returns empty dict in RESP3 connection mode
**Version**: redis-py 5.0.0b2

**Platform**: Any

**Description**: 

RESP2 mode:
```
r = redis.Redis(decode_responses=True)
r.hset("test", "test", '123')
r.hgetall("test")
# {'test': '123'}
```
RESP3 mode:
```
r = redis.Redis(protocol=3, decode_responses=True)
r.hgetall("test")
# {}
```



Discussion:

Resolving patch:
diff --git a/redis/asyncio/client.py b/redis/asyncio/client.py
--- a/redis/asyncio/client.py
+++ b/redis/asyncio/client.py
@@ -255,7 +255,7 @@ def __init__(
 
         self.response_callbacks = CaseInsensitiveDict(self.__class__.RESPONSE_CALLBACKS)
 
-        if self.connection_pool.connection_kwargs.get("protocol") == "3":
+        if self.connection_pool.connection_kwargs.get("protocol") in ["3", 3]:
             self.response_callbacks.update(self.__class__.RESP3_RESPONSE_CALLBACKS)
 
         # If using a single connection client, we need to lock creation-of and use-of
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -1088,7 +1088,7 @@ def __init__(
 
         self.response_callbacks = CaseInsensitiveDict(self.__class__.RESPONSE_CALLBACKS)
 
-        if self.connection_pool.connection_kwargs.get("protocol") == "3":
+        if self.connection_pool.connection_kwargs.get("protocol") in ["3", 3]:
             self.response_callbacks.update(self.__class__.RESP3_RESPONSE_CALLBACKS)
 
     def __repr__(self):


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -479,4 +479,4 @@ def is_resp2_connection(r):
         protocol = r.connection_pool.connection_kwargs.get("protocol")
     elif isinstance(r, redis.RedisCluster):
         protocol = r.nodes_manager.connection_kwargs.get("protocol")
-    return protocol == "2" or protocol is None
+    return protocol in ["2", 2, None]
Repository: redis/redis-py

Issue:
Add support for new redis command CLIENT NO-TOUCH
7.2.0 adds support for the new redis command CLIENT NO-TOUCH. We need to add support, documented [here](https://redis.io/commands/CLIENT-NO-TOUCH).


Discussion:

Resolving patch:
diff --git a/redis/commands/core.py b/redis/commands/core.py
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -761,6 +761,17 @@ def client_no_evict(self, mode: str) -> Union[Awaitable[str], str]:
         """
         return self.execute_command("CLIENT NO-EVICT", mode)
 
+    def client_no_touch(self, mode: str) -> Union[Awaitable[str], str]:
+        """
+        # The command controls whether commands sent by the client will alter
+        # the LRU/LFU of the keys they access.
+        # When turned on, the current client will not change LFU/LRU stats,
+        # unless it sends the TOUCH command.
+
+        For more information see https://redis.io/commands/client-no-touch
+        """
+        return self.execute_command("CLIENT NO-TOUCH", mode)
+
     def command(self, **kwargs):
         """
         Returns dict reply of details about all Redis commands.


Test patch:
diff --git a/tests/test_asyncio/test_commands.py b/tests/test_asyncio/test_commands.py
--- a/tests/test_asyncio/test_commands.py
+++ b/tests/test_asyncio/test_commands.py
@@ -446,6 +446,14 @@ async def test_client_pause(self, r: redis.Redis):
         with pytest.raises(exceptions.RedisError):
             await r.client_pause(timeout="not an integer")
 
+    @skip_if_server_version_lt("7.2.0")
+    @pytest.mark.onlynoncluster
+    async def test_client_no_touch(self, r: redis.Redis):
+        assert await r.client_no_touch("ON") == b"OK"
+        assert await r.client_no_touch("OFF") == b"OK"
+        with pytest.raises(TypeError):
+            await r.client_no_touch()
+
     async def test_config_get(self, r: redis.Redis):
         data = await r.config_get()
         assert "maxmemory" in data
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -693,6 +693,14 @@ def test_client_no_evict(self, r):
         with pytest.raises(TypeError):
             r.client_no_evict()
 
+    @pytest.mark.onlynoncluster
+    @skip_if_server_version_lt("7.2.0")
+    def test_client_no_touch(self, r):
+        assert r.client_no_touch("ON") == b"OK"
+        assert r.client_no_touch("OFF") == b"OK"
+        with pytest.raises(TypeError):
+            r.client_no_touch()
+
     @pytest.mark.onlynoncluster
     @skip_if_server_version_lt("3.2.0")
     def test_client_reply(self, r, r_timeout):
Repository: redis/redis-py

Issue:
Redis.from_url() is a misnomer
**Version**: 4.5.2

**Platform**: Python 3.11.2

**Description**: Redis.from_url is a convenience function, but the kwargs are passed into the ConnectionPool object and not the Redis instance. This formerly wasn't a problem, but it appears as though auto_close_connection_pool now defaults to true, so you can't reliably use Redis.from_url() in a singleton. 



Discussion:

Resolving patch:
diff --git a/redis/asyncio/client.py b/redis/asyncio/client.py
--- a/redis/asyncio/client.py
+++ b/redis/asyncio/client.py
@@ -139,8 +139,12 @@ class initializer. In the case of conflicting arguments, querystring
         arguments always win.
 
         """
+        single_connection_client = kwargs.pop("single_connection_client", False)
         connection_pool = ConnectionPool.from_url(url, **kwargs)
-        return cls(connection_pool=connection_pool)
+        return cls(
+            connection_pool=connection_pool,
+            single_connection_client=single_connection_client,
+        )
 
     def __init__(
         self,
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -899,8 +899,12 @@ class initializer. In the case of conflicting arguments, querystring
         arguments always win.
 
         """
+        single_connection_client = kwargs.pop("single_connection_client", False)
         connection_pool = ConnectionPool.from_url(url, **kwargs)
-        return cls(connection_pool=connection_pool)
+        return cls(
+            connection_pool=connection_pool,
+            single_connection_client=single_connection_client,
+        )
 
     def __init__(
         self,


Test patch:
diff --git a/tests/test_asyncio/test_connection.py b/tests/test_asyncio/test_connection.py
--- a/tests/test_asyncio/test_connection.py
+++ b/tests/test_asyncio/test_connection.py
@@ -271,3 +271,9 @@ async def open_connection(*args, **kwargs):
 
     vals = await asyncio.gather(do_read(), do_close())
     assert vals == [b"Hello, World!", None]
+
+
+@pytest.mark.onlynoncluster
+def test_create_single_connection_client_from_url():
+    client = Redis.from_url("redis://localhost:6379/0?", single_connection_client=True)
+    assert client.single_connection_client is True
diff --git a/tests/test_connection.py b/tests/test_connection.py
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@ -205,3 +205,11 @@ def test_pack_command(Class):
 
     actual = Class().pack_command(*cmd)[0]
     assert actual == expected, f"actual = {actual}, expected = {expected}"
+
+
+@pytest.mark.onlynoncluster
+def test_create_single_connection_client_from_url():
+    client = redis.Redis.from_url(
+        "redis://localhost:6379/0?", single_connection_client=True
+    )
+    assert client.connection is not None
Repository: redis/redis-py

Issue:
Support ZRANK: Added the optional `WITHSCORE` argument.
Documented [here](https://redis.io/commands/ZRANK).


Discussion:

Resolving patch:
diff --git a/redis/commands/core.py b/redis/commands/core.py
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -4654,13 +4654,22 @@ def zrevrangebyscore(
         options = {"withscores": withscores, "score_cast_func": score_cast_func}
         return self.execute_command(*pieces, **options)
 
-    def zrank(self, name: KeyT, value: EncodableT) -> ResponseT:
+    def zrank(
+        self,
+        name: KeyT,
+        value: EncodableT,
+        withscore: bool = False,
+    ) -> ResponseT:
         """
         Returns a 0-based value indicating the rank of ``value`` in sorted set
-        ``name``
+        ``name``.
+        The optional WITHSCORE argument supplements the command's
+        reply with the score of the element returned.
 
         For more information see https://redis.io/commands/zrank
         """
+        if withscore:
+            return self.execute_command("ZRANK", name, value, "WITHSCORE")
         return self.execute_command("ZRANK", name, value)
 
     def zrem(self, name: KeyT, *values: FieldT) -> ResponseT:


Test patch:
diff --git a/tests/test_asyncio/test_commands.py b/tests/test_asyncio/test_commands.py
--- a/tests/test_asyncio/test_commands.py
+++ b/tests/test_asyncio/test_commands.py
@@ -1645,6 +1645,15 @@ async def test_zrank(self, r: redis.Redis):
         assert await r.zrank("a", "a2") == 1
         assert await r.zrank("a", "a6") is None
 
+    @skip_if_server_version_lt("7.2.0")
+    async def test_zrank_withscore(self, r: redis.Redis):
+        await r.zadd("a", {"a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5})
+        assert await r.zrank("a", "a1") == 0
+        assert await r.rank("a", "a2") == 1
+        assert await r.zrank("a", "a6") is None
+        assert await r.zrank("a", "a3", withscore=True) == [2, "3"]
+        assert await r.zrank("a", "a6", withscore=True) is None
+
     async def test_zrem(self, r: redis.Redis):
         await r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
         assert await r.zrem("a", "a2") == 1
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -2581,6 +2581,15 @@ def test_zrank(self, r):
         assert r.zrank("a", "a2") == 1
         assert r.zrank("a", "a6") is None
 
+    @skip_if_server_version_lt("7.2.0")
+    def test_zrank_withscore(self, r: redis.Redis):
+        r.zadd("a", {"a1": 1, "a2": 2, "a3": 3, "a4": 4, "a5": 5})
+        assert r.zrank("a", "a1") == 0
+        assert r.rank("a", "a2") == 1
+        assert r.zrank("a", "a6") is None
+        assert r.zrank("a", "a3", withscore=True) == [2, "3"]
+        assert r.zrank("a", "a6", withscore=True) is None
+
     def test_zrem(self, r):
         r.zadd("a", {"a1": 1, "a2": 2, "a3": 3})
         assert r.zrem("a", "a2") == 1
Repository: redis/redis-py

Issue:
KeyError: 'first-entry' in parse_xinfo_stream
**Version**:

redis-py 4.4.3, redis server 7.0.7

**Platform**:

redis-py on various flavors of Linux (Debian and Ubuntu), redis server in AWS

**Description**:
Sometimes, I get this traceback:

```python
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  .. fastapi stuff elided ...
  File "/serve.py", line 187, in fetch_key
    info = await r.xinfo_stream(key)
  File "venv/lib/python3.9/site-packages/redis/asyncio/client.py", line 505, in execute_command
    return await conn.retry.call_with_retry(
  File "venv/lib/python3.9/site-packages/redis/asyncio/retry.py", line 59, in call_with_retry
    return await do()
  File "venv/lib/python3.9/site-packages/redis/asyncio/client.py", line 481, in _send_command_parse_response
    return await self.parse_response(conn, command_name, **options)
  File "venv/lib/python3.9/site-packages/redis/asyncio/client.py", line 536, in parse_response
    retval = self.response_callbacks[command_name](response, **options)
  File "venv/lib/python3.9/site-packages/redis/client.py", line 323, in parse_xinfo_stream
    first = data["first-entry"]
KeyError: 'first-entry'
```

I haven't gotten it down to a reproducible test case, as it only happens occasionally. The request is automatically retried and works at some point, possibly the second time but it's hard to say for sure. It seems to be some race condition between the stream being created, and info about the stream being available.


Discussion:

Resolving patch:
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -320,7 +320,7 @@ def parse_xautoclaim(response, **options):
 def parse_xinfo_stream(response, **options):
     data = pairs_to_dict(response, decode_keys=True)
     if not options.get("full", False):
-        first = data["first-entry"]
+        first = data.get("first-entry")
         if first is not None:
             data["first-entry"] = (first[0], pairs_to_dict(first[1]))
         last = data["last-entry"]


Test patch: