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

Issue:
distutils is deprecated in Python 3.10
Some alternatives as per the PEP : https://www.python.org/dev/peps/pep-0632/#migration-advice

https://github.com/andymccurdy/redis-py/blob/e19a76c58f2a998d86e51c5a2a0f1db37563efce/redis/connection.py#L1

https://github.com/andymccurdy/redis-py/blob/e19a76c58f2a998d86e51c5a2a0f1db37563efce/tests/conftest.py#L6


Discussion:
Something like this could be done : https://github.com/jamesls/fakeredis/commit/ff1861c249620245305ba1b9e079ce1b1f5ab4e7

Resolving patch:
diff --git a/redis/connection.py b/redis/connection.py
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -1,4 +1,4 @@
-from distutils.version import StrictVersion
+from packaging.version import Version
 from itertools import chain
 from time import time
 from queue import LifoQueue, Empty, Full
@@ -54,13 +54,13 @@
 if HIREDIS_AVAILABLE:
     import hiredis
 
-    hiredis_version = StrictVersion(hiredis.__version__)
+    hiredis_version = Version(hiredis.__version__)
     HIREDIS_SUPPORTS_CALLABLE_ERRORS = \
-        hiredis_version >= StrictVersion('0.1.3')
+        hiredis_version >= Version('0.1.3')
     HIREDIS_SUPPORTS_BYTE_BUFFER = \
-        hiredis_version >= StrictVersion('0.1.4')
+        hiredis_version >= Version('0.1.4')
     HIREDIS_SUPPORTS_ENCODING_ERRORS = \
-        hiredis_version >= StrictVersion('1.0.0')
+        hiredis_version >= Version('1.0.0')
 
     if not HIREDIS_SUPPORTS_BYTE_BUFFER:
         msg = ("redis-py works best with hiredis >= 0.1.4. You're running "


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -3,7 +3,7 @@
 import pytest
 import random
 import redis
-from distutils.version import StrictVersion
+from packaging.version import Version
 from redis.connection import parse_url
 from unittest.mock import Mock
 from urllib.parse import urlparse
@@ -44,7 +44,7 @@ def pytest_sessionstart(session):
 
 def skip_if_server_version_lt(min_version):
     redis_version = REDIS_INFO["version"]
-    check = StrictVersion(redis_version) < StrictVersion(min_version)
+    check = Version(redis_version) < Version(min_version)
     return pytest.mark.skipif(
         check,
         reason="Redis version required >= {}".format(min_version))
@@ -52,7 +52,7 @@ def skip_if_server_version_lt(min_version):
 
 def skip_if_server_version_gte(min_version):
     redis_version = REDIS_INFO["version"]
-    check = StrictVersion(redis_version) >= StrictVersion(min_version)
+    check = Version(redis_version) >= Version(min_version)
     return pytest.mark.skipif(
         check,
         reason="Redis version required < {}".format(min_version))
@@ -183,7 +183,7 @@ def wait_for_command(client, monitor, command):
     # if we find a command with our key before the command we're waiting
     # for, something went wrong
     redis_version = REDIS_INFO["version"]
-    if StrictVersion(redis_version) >= StrictVersion('5.0.0'):
+    if Version(redis_version) >= Version('5.0.0'):
         id_str = str(client.client_id())
     else:
         id_str = '%08x' % random.randrange(2**32)
Repository: redis/redis-py

Issue:
"Discard" transaction functionality is missing
**Version**: What redis-py and what redis version is the issue happening on?
redis version: 3.5.3
Discard transaction functionality is missing

**Platform**: What platform / version? (For example Python 3.5.1 on Windows 7 / Ubuntu 15.10 / Azure)
Python version: 3.8 on Wiindows 10 Enterprise

**Description**: Description of your issue, stack traces from errors and code that reproduces the issue
Discard transaction functionality is currently missing, do you have a rough idea of when will be available? 
I need it to flush all previously queued commands in a transaction and restores the connection state to normal.
Any other way to get it working now with any possible trick?
Thanks


Discussion:

Resolving patch:
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -1802,6 +1802,12 @@ def execute(self, raise_on_error=True):
         finally:
             self.reset()
 
+    def discard(self):
+        """Flushes all previously queued commands
+        See: https://redis.io/commands/DISCARD
+        """
+        self.execute_command("DISCARD")
+
     def watch(self, *names):
         "Watches the values at keys ``names``"
         if self.explicit_transaction:


Test patch:
diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py
--- a/tests/test_pipeline.py
+++ b/tests/test_pipeline.py
@@ -1,7 +1,7 @@
 import pytest
 
 import redis
-from .conftest import wait_for_command
+from .conftest import wait_for_command, skip_if_server_version_lt
 
 
 class TestPipeline:
@@ -353,3 +353,29 @@ def test_pipeline_with_bitfield(self, r):
 
             assert pipe == pipe2
             assert response == [True, [0, 0, 15, 15, 14], b'1']
+
+    @skip_if_server_version_lt('2.0.0')
+    def test_pipeline_discard(self, r):
+
+        # empty pipeline should raise an error
+        with r.pipeline() as pipe:
+            pipe.set('key', 'someval')
+            pipe.discard()
+            with pytest.raises(redis.exceptions.ResponseError):
+                pipe.execute()
+
+        # setting a pipeline and discarding should do the same
+        with r.pipeline() as pipe:
+            pipe.set('key', 'someval')
+            pipe.set('someotherkey', 'val')
+            response = pipe.execute()
+            pipe.set('key', 'another value!')
+            pipe.discard()
+            pipe.set('key', 'another vae!')
+            with pytest.raises(redis.exceptions.ResponseError):
+                pipe.execute()
+
+            pipe.set('foo', 'bar')
+            response = pipe.execute()
+        assert response[0]
+        assert r.get('foo') == b'bar'
Repository: redis/redis-py

Issue:
error in set when ex is a float is confusing
**Version**: redis-py 3.5.3

**Platform**: Python 3.7.3 (default, Jan 22 2021, 20:04:44) [GCC 8.3.0] on linux

**Description**:
```py
>>> import redis
>>> r = redis.Redis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar', ex=10.0)
Traceback (most recent call last):
  File "/redis/client.py", line 1801, in set
    return self.execute_command('SET', *pieces)
  File "/redis/client.py", line 901, in execute_command
    return self.parse_response(conn, command_name, **options)
  File "/redis/client.py", line 915, in parse_response
    response = connection.read_response()
  File "/redis/connection.py", line 756, in read_response
    raise response
redis.exceptions.ResponseError: value is not an integer or out of range
```
This exception is confusing, because it doesn't specify which value is supposed to be an integer. There is a parameter to set called "value", but that's not what caused the exception. It would be better to validate that ex is an integer and raise something like `TypeError: ex must be int or timedelta, not "float"`.


Discussion:

Resolving patch:
diff --git a/redis/commands.py b/redis/commands.py
--- a/redis/commands.py
+++ b/redis/commands.py
@@ -1174,12 +1174,18 @@ def set(self, name, value,
             pieces.append('EX')
             if isinstance(ex, datetime.timedelta):
                 ex = int(ex.total_seconds())
-            pieces.append(ex)
+            if isinstance(ex, int):
+                pieces.append(ex)
+            else:
+                raise DataError("ex must be datetime.timedelta or int")
         if px is not None:
             pieces.append('PX')
             if isinstance(px, datetime.timedelta):
                 px = int(px.total_seconds() * 1000)
-            pieces.append(px)
+            if isinstance(px, int):
+                pieces.append(px)
+            else:
+                raise DataError("px must be datetime.timedelta or int")
         if exat is not None:
             pieces.append('EXAT')
             if isinstance(exat, datetime.datetime):


Test patch:
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -1104,6 +1104,8 @@ def test_set_px(self, r):
         assert r['a'] == b'1'
         assert 0 < r.pttl('a') <= 10000
         assert 0 < r.ttl('a') <= 10
+        with pytest.raises(exceptions.DataError):
+            assert r.set('a', '1', px=10.0)
 
     @skip_if_server_version_lt('2.6.0')
     def test_set_px_timedelta(self, r):
@@ -1116,6 +1118,8 @@ def test_set_px_timedelta(self, r):
     def test_set_ex(self, r):
         assert r.set('a', '1', ex=10)
         assert 0 < r.ttl('a') <= 10
+        with pytest.raises(exceptions.DataError):
+            assert r.set('a', '1', ex=10.0)
 
     @skip_if_server_version_lt('2.6.0')
     def test_set_ex_timedelta(self, r):
Repository: redis/redis-py

Issue:
4.0.0b1 breaks script_flush on pre-6.2 server
**Version**: redis-py 4.0.0b1, redis 5.0.7

**Platform**: Python 3.8.10 on Ubunutu 20.04

**Description**: In 4.0.0b1, the implementation of `script_flush` always calls either `SCRIPT FLUSH SYNC` or `SCRIPT FLUSH ASYNC` on the server. However, the SYNC/ASYNC modifier was only added in Redis 6.2, making it fail on older versions.

To reproduce (assuming a Redis server on localhost):
```python
import redis
r = redis.Redis('localhost')
r.script_flush()
```

Result: `ResponseError: Unknown subcommand or wrong number of arguments for 'FLUSH'. Try SCRIPT HELP.`

Apart from wanting to support older Redis versions, the [documentation](https://redis.io/commands/script-flush) suggests that providing neither modifier is not simply equivalent to providing SYNC. Rather, it leaves it up to a configuration setting on the server, and I feel like calling `r.script_flush()` should respect that server-side default.


Discussion:

Resolving patch:
diff --git a/redis/commands.py b/redis/commands.py
--- a/redis/commands.py
+++ b/redis/commands.py
@@ -2922,16 +2922,22 @@ def script_debug(self, *args):
             "SCRIPT DEBUG is intentionally not implemented in the client."
         )
 
-    def script_flush(self, sync_type="SYNC"):
+    def script_flush(self, sync_type=None):
         """Flush all scripts from the script cache.
         ``sync_type`` is by default SYNC (synchronous) but it can also be
                       ASYNC.
         See: https://redis.io/commands/script-flush
         """
-        if sync_type not in ["SYNC", "ASYNC"]:
-            raise DataError("SCRIPT FLUSH defaults to SYNC or "
-                            "accepts SYNC/ASYNC")
-        pieces = [sync_type]
+
+        # Redis pre 6 had no sync_type.
+        if sync_type not in ["SYNC", "ASYNC", None]:
+            raise DataError("SCRIPT FLUSH defaults to SYNC in redis > 6.2, or "
+                            "accepts SYNC/ASYNC. For older versions, "
+                            "of redis leave as None.")
+        if sync_type is None:
+            pieces = []
+        else:
+            pieces = [sync_type]
         return self.execute_command('SCRIPT FLUSH', *pieces)
 
     def script_kill(self):


Test patch:
diff --git a/tests/test_scripting.py b/tests/test_scripting.py
--- a/tests/test_scripting.py
+++ b/tests/test_scripting.py
@@ -43,6 +43,10 @@ def test_script_flush(self, r):
         r.script_load(multiply_script)
         r.script_flush()
 
+        r.set('a', 2)
+        r.script_load(multiply_script)
+        r.script_flush(None)
+
         with pytest.raises(exceptions.DataError):
             r.set('a', 2)
             r.script_load(multiply_script)
Repository: redis/redis-py

Issue:
Misleading docstring of class `Redis`
My impression is that [this docstring](https://github.com/andymccurdy/redis-py/blob/3.5.3/redis/client.py#L526) is misleading:

```py
class Redis:
    """
    Implementation of the Redis protocol.

    This abstract class provides a Python interface to all Redis commands
    and an implementation of the Redis protocol.

    Connection and Pipeline derive from this, implementing how
    the commands are sent and received to the Redis server
    """
```

At least in terms of OOP (object-oriented programming), the class [`Connection`](https://github.com/andymccurdy/redis-py/blob/3.5.3/redis/connection.py#L497) *does not* derive from `Redis` since at least 2017.
(`Pipeline`, however, does.)

This seems especially relevant as `Redis` and `Connection` are somewhat used interchangeably in the wild; for example in rq, where I'm currently investigating [this issue](https://github.com/rq/rq/issues/1398) which arises from `Connection` implementation-specific keyword arguments being obtained from a connection pool and passed to `Redis`' constructor as if that would be a connection class itself.


Discussion:

Resolving patch:
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -613,8 +613,10 @@ class Redis(RedisModuleCommands, CoreCommands, object):
     This abstract class provides a Python interface to all Redis commands
     and an implementation of the Redis protocol.
 
-    Connection and Pipeline derive from this, implementing how
-    the commands are sent and received to the Redis server
+    Pipelines derive from this, implementing how
+    the commands are sent and received to the Redis server. Based on
+    configuration, an instance will either use a ConnectionPool, or
+    Connection object to talk to redis.
     """
     RESPONSE_CALLBACKS = {
         **string_keys_to_dict(


Test patch:
Repository: redis/redis-py

Issue:
CI run to install the built package
In light of bug #1645  we should amend our CI run to install the built package, in a new virtual env and run something simple like a redis.Redis().ping(). Eventually we could build up to running the full integration test against the package.
CI run to install the built package
In light of bug #1645  we should amend our CI run to install the built package, in a new virtual env and run something simple like a redis.Redis().ping(). Eventually we could build up to running the full integration test against the package.


Discussion:

Resolving patch:
diff --git a/tasks.py b/tasks.py
--- a/tasks.py
+++ b/tasks.py
@@ -56,4 +56,4 @@ def clean(c):
 @task
 def package(c):
     """Create the python packages"""
-    run("python setup.py build install")
+    run("python setup.py sdist bdist_wheel")


Test patch:
diff --git a/.github/workflows/install_and_test.sh b/.github/workflows/install_and_test.sh
new file mode 100755
--- /dev/null
+++ b/.github/workflows/install_and_test.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+set -e
+
+SUFFIX=$1
+if [ -z ${SUFFIX} ]; then
+    echo "Supply valid python package extension such as whl or tar.gz. Exiting."
+    exit 3
+fi
+
+script=`pwd`/${BASH_SOURCE[0]}
+HERE=`dirname ${script}`
+ROOT=`realpath ${HERE}/../..`
+
+cd ${ROOT}
+DESTENV=${ROOT}/.venvforinstall
+if [ -d ${DESTENV} ]; then
+    rm -rf ${DESTENV}
+fi
+python -m venv ${DESTENV}
+source ${DESTENV}/bin/activate
+pip install --upgrade --quiet pip
+pip install --quiet -r dev_requirements.txt
+invoke devenv
+invoke package
+
+# find packages
+PKG=`ls ${ROOT}/dist/*.${SUFFIX}`
+ls -l ${PKG}
+
+TESTDIR=${ROOT}/STAGETESTS
+if [ -d ${TESTDIR} ]; then
+    rm -rf ${TESTDIR}
+fi
+mkdir ${TESTDIR}
+cp -R ${ROOT}/tests ${TESTDIR}/tests
+cd ${TESTDIR}
+
+# install, run tests
+pip install ${PKG}
+pytest
Repository: redis/redis-py

Issue:
4.0.0rc1 breaks various zrange commands on older servers
**Version**: redis-py 4.0.0rc1, redis 6.0.16 (or any less than 6.2).

**Platform**: Python 3.8, Ubuntu 20.04

**Description**:

Previously calling `zrevrange` or `zrange(..., desc=True)` would use ZREVRANGE on the wire. Somewhere between 4.0.0b1 and 4.0.0rc1 this changed to use `ZRANGE ... REV`, which is new syntax in Redis 6.2. When using an older server this causes a syntax error.

To reproduce:
```python
import redis
r = redis.Redis('localhost')
r.zrevrange('foo', 0, -1)
```

Other commands are also affected e.g. zrangebyscore and zrangebylex are also using ZRANGE with options on the wire which is not supported pre-6.2.


Discussion:
@chayim looks like this was broken by #1603.
Thanks @bmerry for tracking this down all the way. We'll definitely get this into rc2!  @AvitalFineRedis while we're here, let's test for this case.


@chayim the following is still broken in 4.0.0rc2 (but worked in 3.5.3):
```
import redis
r = redis.Redis('localhost')
r.zrange('foo', 0, -1, desc=True)
```
@AvitalFineRedis can you add a test with this specific case? Our 6.0.0 testing didn't seem to cover this.

@bmerry thanks again, for highlighting this. 

Resolving patch:
diff --git a/redis/commands/core.py b/redis/commands/core.py
--- a/redis/commands/core.py
+++ b/redis/commands/core.py
@@ -2520,6 +2520,13 @@ def zrange(self, name, start, end, desc=False, withscores=False,
         ``offset`` and ``num`` are specified, then return a slice of the range.
         Can't be provided when using ``bylex``.
         """
+        # Need to support ``desc`` also when using old redis version
+        # because it was supported in 3.5.3 (of redis-py)
+        if not byscore and not bylex and (offset is None and num is None) \
+                and desc:
+            return self.zrevrange(name, start, end, withscores,
+                                  score_cast_func)
+
         return self._zrange('ZRANGE', None, name, start, end, desc, byscore,
                             bylex, withscores, score_cast_func, offset, num)
 


Test patch:
diff --git a/tests/test_commands.py b/tests/test_commands.py
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -1867,6 +1867,7 @@ def test_zrange(self, r):
         assert r.zrange('a', 0, 1) == [b'a1', b'a2']
         assert r.zrange('a', 1, 2) == [b'a2', b'a3']
         assert r.zrange('a', 0, 2) == [b'a1', b'a2', b'a3']
+        assert r.zrange('a', 0, 2, desc=True) == [b'a3', b'a2', b'a1']
 
         # withscores
         assert r.zrange('a', 0, 1, withscores=True) == \
Repository: redis/redis-py

Issue:
AttributeError: 'Redis' object has no attribute 'sentinel_masters'
**Version**: 4.0.0

**Platform**: Python 3.7.12 / alpine / Kubernetes 1.20 / AWS / Redis server v=6.0.16 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=cb8b7c1889d3b7df

**Description**: Unable to call sentinel.discover_master()

When attempting to return the redis master from the sentinel hosts using `py-redis 4.0.0` using the discover_master SentinelCommand I receive the following Attribute error. 

```AttributeError: 'Redis' object has no attribute 'sentinel_masters'```

I would expect to see a list of tuples containing the list of redis master ip/port

```
[('10.10.10.10', 6379)]
```

It looks like the `Redis` client object returned when setting up the Sentinel class doesn't have access to the `sentinel_master` command found here https://github.com/redis/redis-py/blob/master/redis/commands/sentinel.py#L20 or any of the commands in that class.

I have taken a look at the Redis class and can't find where `sentinel.py` is passing through the sentinel commands or where the `Redis` class in `client.py` is loading them.

**Example**:

```python
Python 3.7.12 (default, Nov 13 2021, 04:28:59)
[GCC 10.3.1 20210424] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from redis.sentinel import Sentinel
/usr/local/lib/python3.7/site-packages/redis/connection.py:77: UserWarning: redis-py works best with hiredis. Please consider installing
  warnings.warn(msg)
>>> sentinel = Sentinel([('localhost', 5000)], socket_timeout=0.1)
>>> master = sentinel.discover_master('mymaster')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/site-packages/redis/sentinel.py", line 234, in discover_master
    masters = sentinel.sentinel_masters()
AttributeError: 'Redis' object has no attribute 'sentinel_masters'
```

I tried using version 3.5.3 and I don't get the error and the master host/port is returned in a tuple, so it would seem the problem is specific to version 4.0.0. I have tried with some of the RC releases and they have the problem. The only strange thing is that I was using the same code last week (and presumebly py-redis 4.0.0) and the code worked.




Discussion:

Resolving patch:
diff --git a/redis/client.py b/redis/client.py
--- a/redis/client.py
+++ b/redis/client.py
@@ -6,7 +6,8 @@
 import threading
 import time
 import warnings
-from redis.commands import CoreCommands, RedisModuleCommands, list_or_args
+from redis.commands import (CoreCommands, RedisModuleCommands,
+                            SentinelCommands, list_or_args)
 from redis.connection import (ConnectionPool, UnixDomainSocketConnection,
                               SSLConnection)
 from redis.lock import Lock
@@ -606,7 +607,7 @@ def parse_set_result(response, **options):
     return response and str_if_bytes(response) == 'OK'
 
 
-class Redis(RedisModuleCommands, CoreCommands, object):
+class Redis(RedisModuleCommands, CoreCommands, SentinelCommands, object):
     """
     Implementation of the Redis protocol.
 


Test patch:
Repository: redis/redis-py

Issue:
Remove hiredis warning
**Version**: What redis-py and what redis version is the issue happening on?

4.0.1

**Platform**: What platform / version? (For example Python 3.5.1 on Windows 7 / Ubuntu 15.10 / Azure)

M1 Mac OS 11.6, python 3.8.12

**Description**: Description of your issue, stack traces from errors and code that reproduces the issue

Importing redis still causes the `redis-py works best with hiredis. Please consider installing` warning. It looks like #1721 intended to fix this, but didn't quite remove the message in enough places.  



Discussion:

Resolving patch:
diff --git a/redis/__init__.py b/redis/__init__.py
--- a/redis/__init__.py
+++ b/redis/__init__.py
@@ -37,7 +37,7 @@ def int_or_str(value):
         return value
 
 
-__version__ = "4.0.1"
+__version__ = "4.0.2"
 
 
 VERSION = tuple(map(int_or_str, __version__.split('.')))
diff --git a/redis/connection.py b/redis/connection.py
--- a/redis/connection.py
+++ b/redis/connection.py
@@ -9,7 +9,6 @@
 import os
 import socket
 import threading
-import warnings
 import weakref
 
 from redis.exceptions import (
@@ -67,9 +66,6 @@
     # only use byte buffer if hiredis supports it
     if not HIREDIS_SUPPORTS_BYTE_BUFFER:
         HIREDIS_USE_BYTE_BUFFER = False
-else:
-    msg = "redis-py works best with hiredis. Please consider installing"
-    warnings.warn(msg)
 
 SYM_STAR = b'*'
 SYM_DOLLAR = b'$'


Test patch: