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

Issue:
SentinelManagedConnection.read_response() got an unexpected keyword argument 'push_request'
Version: 3.5.3
Platform: Python 3.10 on MacOS 13.3.1

Description:
[redis.client.PubSub().parse_response()](https://github.com/redis/redis-py/blob/master/redis/client.py#L777) is calling [SentinelManagedConnection.read_response()](https://github.com/redis/redis-py/blob/master/redis/sentinel.py#L57) with a non-existent `push_request` keyword argument.

```
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 1108, in run
    pubsub.get_message(ignore_subscribe_messages=True, timeout=sleep_time)
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 983, in get_message
    response = self.parse_response(block=(timeout is None), timeout=timeout)
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 796, in parse_response
    response = self._execute(conn, try_read)
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 772, in _execute
    return conn.retry.call_with_retry(
  File "/usr/local/lib/python3.10/site-packages/redis/retry.py", line 46, in call_with_retry
    return do()
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 773, in <lambda>
  File "/usr/local/lib/python3.10/site-packages/redis/client.py", line 794, in try_read
    return conn.read_response(disconnect_on_error=False, push_request=True)
TypeError: SentinelManagedConnection.read_response() got an unexpected keyword argument 'push_request'
```

This issue looks identical to #2754 


Discussion:

Resolving patch:
diff --git a/redis/sentinel.py b/redis/sentinel.py
--- a/redis/sentinel.py
+++ b/redis/sentinel.py
@@ -55,12 +55,17 @@ def connect(self):
         return self.retry.call_with_retry(self._connect_retry, lambda error: None)
 
     def read_response(
-        self, disable_decoding=False, *, disconnect_on_error: Optional[bool] = False
+        self,
+        disable_decoding=False,
+        *,
+        disconnect_on_error: Optional[bool] = False,
+        push_request: Optional[bool] = False,
     ):
         try:
             return super().read_response(
                 disable_decoding=disable_decoding,
                 disconnect_on_error=disconnect_on_error,
+                push_request=push_request,
             )
         except ReadOnlyError:
             if self.connection_pool.is_master:


Test patch:
Repository: redis/redis-py

Issue:
async Sentinel is broken for pubsub
**Version**: 5.0.0

**Description**: async client with Sentinel is broken for pubsub (similar to the [issue](https://github.com/redis/redis-py/issues/2893) for synchronous one that already fixed): `redis.asyncio.client.PubSub.parse_response()` is calling `redis.asyncio.sentinel.SentinelManagedConnection.read_response()` with unexpected `push_request` argument

<img width="646" alt="Снимок экрана 2023-08-31 в 13 38 10" src="https://github.com/redis/redis-py/assets/50031404/67ae739d-84a3-4e5c-ba97-95be6e2d5557">




Discussion:

Resolving patch:
diff --git a/redis/asyncio/sentinel.py b/redis/asyncio/sentinel.py
--- a/redis/asyncio/sentinel.py
+++ b/redis/asyncio/sentinel.py
@@ -69,12 +69,14 @@ async def read_response(
         timeout: Optional[float] = None,
         *,
         disconnect_on_error: Optional[float] = True,
+        push_request: Optional[bool] = False,
     ):
         try:
             return await super().read_response(
                 disable_decoding=disable_decoding,
                 timeout=timeout,
                 disconnect_on_error=disconnect_on_error,
+                push_request=push_request,
             )
         except ReadOnlyError:
             if self.connection_pool.is_master:


Test patch:
Repository: redis/redis-py

Issue:
RPUSHX does not support multiple elements
[RPUSHX](https://redis.io/commands/rpushx/) allows multiple elements, but the redis-py call only accepts a single value ([source](https://github.com/redis/redis-py/blob/1596ac6a0bbc1e00e57c6a48e255a8f917498e39/redis/commands/core.py#L2826)).

LPUSHX does accept multiple values, so I don't think there was any sort of technical limitation for supporting this? ([source](https://github.com/redis/redis-py/blob/1596ac6a0bbc1e00e57c6a48e255a8f917498e39/redis/commands/core.py#L2736))

 
**Version**: redis-py: 5.0.0 redis 5.0.7

**Platform**: Python 3.9.18

**Description**: See above

related PR: https://github.com/redis/redis-py/pull/1559/



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
@@ -2823,13 +2823,13 @@ def rpush(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]:
         """
         return self.execute_command("RPUSH", name, *values)
 
-    def rpushx(self, name: str, value: str) -> Union[Awaitable[int], int]:
+    def rpushx(self, name: str, *values: str) -> Union[Awaitable[int], int]:
         """
         Push ``value`` onto the tail of the list ``name`` if ``name`` exists
 
         For more information see https://redis.io/commands/rpushx
         """
-        return self.execute_command("RPUSHX", name, value)
+        return self.execute_command("RPUSHX", name, *values)
 
     def lpos(
         self,


Test patch:
Repository: redis/redis-py

Issue:
Redis.json().objlen returns type list instead of int
**Version**: redis-stack-server:7.2.0-v2 via docker; redis-py 5.0.0

**Platform**: macOS

**Description**: Redis.json().objlen returns type list instead of int. The typing hint suggests it should return int instead of list. In redis-cli, it does return int though.


Discussion:
per the documentation, it returns an array. 

https://redis.io/commands/json.objlen/#examples

> JSON.OBJLEN returns an array of integer replies for each path specified as the number of keys in the object or nil, if the matching JSON value is not an object.

the type hint should probably be fixed.
> per the documentation, it returns an array.
> 
> https://redis.io/commands/json.objlen/#examples
> 
> > JSON.OBJLEN returns an array of integer replies for each path specified as the number of keys in the object or nil, if the matching JSON value is not an object.
> 
> the type hint should probably be fixed.

Sorry my bad, objlen of redis-cli indeed returns list but the type hint is left unchanged in 5.0.1. I've just tested the 5.0.1 api and it still returns list.
https://github.com/redis/redis-py/blob/cc4bc1a544d1030aec1696baef2861064fa8dd1c/redis/commands/json/commands.py#L124

Resolving patch:
diff --git a/redis/commands/json/commands.py b/redis/commands/json/commands.py
--- a/redis/commands/json/commands.py
+++ b/redis/commands/json/commands.py
@@ -121,7 +121,9 @@ def objkeys(
         """  # noqa
         return self.execute_command("JSON.OBJKEYS", name, str(path), keys=[name])
 
-    def objlen(self, name: str, path: Optional[str] = Path.root_path()) -> int:
+    def objlen(
+        self, name: str, path: Optional[str] = Path.root_path()
+    ) -> List[Optional[int]]:
         """Return the length of the dictionary JSON value under ``path`` at key
         ``name``.
 


Test patch:
Repository: redis/redis-py

Issue:
resp3 parser async parser incorrectly parses maps
Issue discovered in pr #2947

the evaulation order of `key:val` in `{key():val() for foo in bar}` dict comprehension is undefined in Python.  It mostly is left-right,
but some versions, notably recent 3.7 versions, don't behave that way.  It is best to use explicit ordering when reading from  a stream.

This had already been fixed for __non-async__ parsing, but in pr #2947 caused some scheduling behaviour which triggered this to happen. A fix for __async__ has been added there.



Discussion:

Resolving patch:
diff --git a/redis/_parsers/resp3.py b/redis/_parsers/resp3.py
--- a/redis/_parsers/resp3.py
+++ b/redis/_parsers/resp3.py
@@ -96,8 +96,9 @@ def _read_response(self, disable_decoding=False, push_request=False):
                 pass
         # map response
         elif byte == b"%":
-            # we use this approach and not dict comprehension here
-            # because this dict comprehension fails in python 3.7
+            # We cannot use a dict-comprehension to parse stream.
+            # Evaluation order of key:val expression in dict comprehension only
+            # became defined to be left-right in version 3.8
             resp_dict = {}
             for _ in range(int(response)):
                 key = self._read_response(disable_decoding=disable_decoding)
@@ -225,12 +226,16 @@ async def _read_response(
                 pass
         # map response
         elif byte == b"%":
-            response = {
-                (await self._read_response(disable_decoding=disable_decoding)): (
-                    await self._read_response(disable_decoding=disable_decoding)
+            # We cannot use a dict-comprehension to parse stream.
+            # Evaluation order of key:val expression in dict comprehension only
+            # became defined to be left-right in version 3.8
+            resp_dict = {}
+            for _ in range(int(response)):
+                key = await self._read_response(disable_decoding=disable_decoding)
+                resp_dict[key] = await self._read_response(
+                    disable_decoding=disable_decoding, push_request=push_request
                 )
-                for _ in range(int(response))
-            }
+            response = resp_dict
         # push response
         elif byte == b">":
             response = [


Test patch:
Repository: redis/redis-py

Issue:
`disable_decoding` not used in async version of `read_response`.
**Version**: redis-py version - 5.0.0 (I still see it on main)

**Description**:
Is there a reason why `disable_decoding` is not being used in async version of `read_response`? 
It seems like there's no async way to get raw data (`NEVER_DECODE`) from Redis.
Are there any plans of adding the `NEVER_DECODE` support for async `read_response`?
We want to save pickled data (not compatible with `UTF-8`) in Redis, and for now we will use the workaround (as in https://github.com/redis/redis-py/issues/1006#issuecomment-1100506453 ), but it's not a very clean solution.

redis/_parsers/hiredis.py:204
https://github.com/redis/redis-py/blob/d3a3ada03e080f39144807c9fbe44876c40e0548/redis/_parsers/hiredis.py#L192-L217




Discussion:
Hi @MrDenkoV Thanks for reporting this!
I think there is no reason for it and it's a bug.
Do you want to open a PR and fix this? feel free if not, I can do it myself.
Hi @dvora-h Thank you for your quick response!
I will open a PR and fix it, as it seems you haven't started yet.

Resolving patch:
diff --git a/redis/_parsers/hiredis.py b/redis/_parsers/hiredis.py
--- a/redis/_parsers/hiredis.py
+++ b/redis/_parsers/hiredis.py
@@ -198,10 +198,16 @@ async def read_response(
         if not self._connected:
             raise ConnectionError(SERVER_CLOSED_CONNECTION_ERROR) from None
 
-        response = self._reader.gets()
+        if disable_decoding:
+            response = self._reader.gets(False)
+        else:
+            response = self._reader.gets()
         while response is False:
             await self.read_from_socket()
-            response = self._reader.gets()
+            if disable_decoding:
+                response = self._reader.gets(False)
+            else:
+                response = self._reader.gets()
 
         # if the response is a ConnectionError or the response is a list and
         # the first item is a ConnectionError, raise it as something bad


Test patch:
Repository: redis/redis-py

Issue:
"bug" about acl_genpass method
Thanks for wanting to report an issue you've found in redis-py.    Please delete this text and fill in the template below.
It is of course not always possible to reduce your code to a small test case, but it's highly appreciated to have as much data as possible.    Thank you!

**Version**: 5.0.1, "bug" about acl_genpass method

**Platform**: win11

**Description**: Refer to the following demo

demo:

```python
from redis import Redis

url = "redis://localhost:6379/1"
rdb = Redis.from_url(url)

print(rdb.acl_genpass(32))
```

This script is similar to `ACL GENPASS [bits]`, we will get an 8-digit password. But what we got didn't meet expectations.

Your source code might get the desired result this way:

```python
    def acl_genpass(self, bits: Union[int, None] = None, **kwargs) -> ResponseT:
        """Generate a random password value.
        If ``bits`` is supplied then use this number of bits, rounded to
        the next multiple of 4.
        See: https://redis.io/commands/acl-genpass
        """
        pieces = []
        if bits is not None:
            try:
                b = int(bits)
                if b < 0 or b > 4096:
                    raise ValueError
                pieces.append(b)
            except ValueError:
                raise DataError(
                    "genpass optionally accepts a bits argument, between 0 and 4096."
                )
        return self.execute_command("ACL GENPASS", *pieces, **kwargs)
```




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
@@ -97,6 +97,7 @@ def acl_genpass(self, bits: Union[int, None] = None, **kwargs) -> ResponseT:
                 b = int(bits)
                 if b < 0 or b > 4096:
                     raise ValueError
+                pieces.append(b)
             except ValueError:
                 raise DataError(
                     "genpass optionally accepts a bits argument, between 0 and 4096."


Test patch:
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -201,8 +201,9 @@ def test_acl_genpass(self, r):
             r.acl_genpass(-5)
             r.acl_genpass(5555)
 
-        r.acl_genpass(555)
+        password = r.acl_genpass(555)
         assert isinstance(password, (str, bytes))
+        assert len(password) == 139
 
     @skip_if_server_version_lt("7.0.0")
     @skip_if_redis_enterprise()
Repository: redis/redis-py

Issue:
`redis.asyncio.cluster.ClusterPipeline.__bool__()` should always return True
**Version**:
redis-py 5.0.1

**Platform**:
CPython 3.11.6 on Fargate for arm64

**Description**:
In #994 it was agreed that pipelines should never be considered "false-y", i.e. always evaluate to True. The change was applied in 8b76019. Since then, asyncio and cluster support were merged and it appears as if asyncio ClusterPipeline instances currently behave differently than other pipeline instances. This is due to the following line:
https://github.com/redis/redis-py/blob/58da813e2ed3ce45d9bc14fff8d0a378b0f5ee82/redis/asyncio/cluster.py#L1432C29-L1432C29

Could you please harmonize the truth value of all pipeline types, i.e. make asyncio ClusterPipeline instances always evaluate to True?


Discussion:

Resolving patch:
diff --git a/redis/asyncio/cluster.py b/redis/asyncio/cluster.py
--- a/redis/asyncio/cluster.py
+++ b/redis/asyncio/cluster.py
@@ -1429,7 +1429,8 @@ def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None:
         self._command_stack = []
 
     def __bool__(self) -> bool:
-        return bool(self._command_stack)
+        "Pipeline instances should  always evaluate to True on Python 3+"
+        return True
 
     def __len__(self) -> int:
         return len(self._command_stack)


Test patch:
diff --git a/tests/test_asyncio/test_pipeline.py b/tests/test_asyncio/test_pipeline.py
--- a/tests/test_asyncio/test_pipeline.py
+++ b/tests/test_asyncio/test_pipeline.py
@@ -7,7 +7,6 @@
 
 
 class TestPipeline:
-    @pytest.mark.onlynoncluster
     async def test_pipeline_is_true(self, r):
         """Ensure pipeline instances are not false-y"""
         async with r.pipeline() as pipe:
Repository: redis/redis-py

Issue:
`hset` and `hmset` unexpectedly mutates the list passed to `items` if `key`+`value` or `mapping` is also used
**Version**: redis-py 5.0.1 (Any Redis version)

**Platform**: Any platform

**Description**:
If the `items` parameter of the  `hset` or `hmset` method is used in conjunction with the `key` and `value`, or with the `mapping` parameters, the list passed to the `items` parameter is unexpectedly mutated.

For example, using the code below:

```python
from redis.client import Redis

redis = Redis.from_url('redis://127.0.0.1')

items = [
    'one', b'1',
    'two', b'2',
    'three', b'3',
]

redis.hset('test', items=items, key='four', value=b'4')

print(items)

redis.close()
```

After the method call, `items` is expectantly updated to `['one', b'1', 'two', b'2', 'three', b'3', 'four', b'4']`.

Calling the method should, in principle, not change any of the objects sent as parameters.

As a suggestion, the code could be changed to:

```python
        if key is None and not mapping and not items:
            raise DataError("'hset' with no key value pairs")

        sources = []
        
        if items:
            sources.append(items)
        
        if key is not None:
            sources.append((key, value))
        
        if mapping:
            sources.append(value for entry in mapping.items() for value in entry)

        return self.execute_command("HSET", name, *chain(*sources))
```

This would have the added benefit of allowing `items` to be any kind of `Iterable` object and not just lists.

(In the same vein of ideas, the `mapping` parameter could be changed to `typing.Mapping` to allow any mapping instead of just dicts)


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
@@ -5017,14 +5017,16 @@ def hset(
         """
         if key is None and not mapping and not items:
             raise DataError("'hset' with no key value pairs")
-        items = items or []
+        pieces = []
+        if items:
+            pieces.extend(items)
         if key is not None:
-            items.extend((key, value))
+            pieces.extend((key, value))
         if mapping:
             for pair in mapping.items():
-                items.extend(pair)
+                pieces.extend(pair)
 
-        return self.execute_command("HSET", name, *items)
+        return self.execute_command("HSET", name, *pieces)
 
     def hsetnx(self, name: str, key: str, value: str) -> Union[Awaitable[bool], bool]:
         """


Test patch:
Repository: redis/redis-py

Issue:
Typing for address_remap is incorrect
**Version**: 5.0.4

**Platform**: Python 3.12.3 on Debian Bookworm

**Description**: Typing for `address_remap` is as separate args but it's actually a tuple



Discussion:

Resolving patch:
diff --git a/redis/asyncio/cluster.py b/redis/asyncio/cluster.py
--- a/redis/asyncio/cluster.py
+++ b/redis/asyncio/cluster.py
@@ -275,7 +275,7 @@ def __init__(
         ssl_min_version: Optional[ssl.TLSVersion] = None,
         ssl_ciphers: Optional[str] = None,
         protocol: Optional[int] = 2,
-        address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None,
+        address_remap: Optional[Callable[[Tuple[str, int]], Tuple[str, int]]] = None,
         cache_enabled: bool = False,
         client_cache: Optional[AbstractCache] = None,
         cache_max_size: int = 100,
@@ -1152,7 +1152,7 @@ def __init__(
         startup_nodes: List["ClusterNode"],
         require_full_coverage: bool,
         connection_kwargs: Dict[str, Any],
-        address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None,
+        address_remap: Optional[Callable[[Tuple[str, int]], Tuple[str, int]]] = None,
     ) -> None:
         self.startup_nodes = {node.name: node for node in startup_nodes}
         self.require_full_coverage = require_full_coverage
diff --git a/redis/cluster.py b/redis/cluster.py
--- a/redis/cluster.py
+++ b/redis/cluster.py
@@ -506,7 +506,7 @@ def __init__(
         read_from_replicas: bool = False,
         dynamic_startup_nodes: bool = True,
         url: Optional[str] = None,
-        address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None,
+        address_remap: Optional[Callable[[Tuple[str, int]], Tuple[str, int]]] = None,
         **kwargs,
     ):
         """
@@ -1347,7 +1347,7 @@ def __init__(
         lock=None,
         dynamic_startup_nodes=True,
         connection_pool_class=ConnectionPool,
-        address_remap: Optional[Callable[[str, int], Tuple[str, int]]] = None,
+        address_remap: Optional[Callable[[Tuple[str, int]], Tuple[str, int]]] = None,
         **kwargs,
     ):
         self.nodes_cache = {}


Test patch:
Repository: redis/redis-py

Issue:
Discrepancy in `INFO` response parsing
**Version**: `5.0.0`

**Description**: The code for parsing the `INFO` response is creating a discrepancy in the new RediSearch index field types field, e.g., `search_fields_text`.
If there is more than one section to this field its corresponding value (e.g., `TEXT=1, SORTABLE=1`) is returned as a dictionary (as expected), while if there is only one value for it (e.g., `TEXT=1`) it is returned as a string!

This is bad since we later use this value assuming that it is a dictionary, and thus face failures in the case that it is not.
The wanted behavior: We always get a dictionary back, whether we have only one section for this value or more.

Example: We have one section for the `TEXT` field, and two for the `TAG` field, and this is what we get:
![image](https://github.com/redis/redis-py/assets/74051729/51282024-7e1c-4d2a-bae8-04dcaf0fc53e)

The source of the problem is in the `parse_info()` function, [here](https://github.com/redis/redis-py/blob/19b55c62389c890a96dd611e28aaaedba7506720/redis/_parsers/helpers.py#L35-L36).

Thanks!



Discussion:

Resolving patch:
diff --git a/redis/_parsers/helpers.py b/redis/_parsers/helpers.py
--- a/redis/_parsers/helpers.py
+++ b/redis/_parsers/helpers.py
@@ -38,7 +38,7 @@ def parse_info(response):
     response = str_if_bytes(response)
 
     def get_value(value):
-        if "," not in value or "=" not in value:
+        if "," not in value and "=" not in value:
             try:
                 if "." in value:
                     return float(value)


Test patch:
diff --git a/tests/test_parsers/test_helpers.py b/tests/test_parsers/test_helpers.py
new file mode 100644
--- /dev/null
+++ b/tests/test_parsers/test_helpers.py
@@ -0,0 +1,35 @@
+from redis._parsers.helpers import parse_info
+
+
+def test_parse_info():
+    info_output = """
+# Modules
+module:name=search,ver=999999,api=1,filters=0,usedby=[],using=[ReJSON],options=[handle-io-errors]
+
+# search_fields_statistics
+search_fields_text:Text=3
+search_fields_tag:Tag=2,Sortable=1
+
+# search_version
+search_version:99.99.99
+search_redis_version:7.2.2 - oss
+
+# search_runtime_configurations
+search_query_timeout_ms:500
+    """
+    info = parse_info(info_output)
+
+    assert isinstance(info["modules"], list)
+    assert isinstance(info["modules"][0], dict)
+    assert info["modules"][0]["name"] == "search"
+
+    assert isinstance(info["search_fields_text"], dict)
+    assert info["search_fields_text"]["Text"] == 3
+
+    assert isinstance(info["search_fields_tag"], dict)
+    assert info["search_fields_tag"]["Tag"] == 2
+    assert info["search_fields_tag"]["Sortable"] == 1
+
+    assert info["search_version"] == "99.99.99"
+    assert info["search_redis_version"] == "7.2.2 - oss"
+    assert info["search_query_timeout_ms"] == 500