Skip to content

Confirm support for Django 5.2. #769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
- '4.2'
- '5.0'
- '5.1'
- '5.2'
redis-version:
- 'latest'

Expand All @@ -38,7 +39,7 @@ jobs:
python-version: '3.9'

# latest Django with pre-release redis
- django-version: '5.1'
- django-version: '5.2'
redis-version: 'master'
python-version: '3.12'

Expand Down
2 changes: 2 additions & 0 deletions changelog.d/824.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Confirm support for Django 5.2.
Fix shadowing builtin Python exceptions.
15 changes: 11 additions & 4 deletions django_redis/client/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,21 @@
from django.core.exceptions import ImproperlyConfigured
from django.utils.module_loading import import_string
from redis import Redis
from redis.exceptions import ConnectionError, ResponseError, TimeoutError
from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import ResponseError
from redis.exceptions import TimeoutError as RedisTimeoutError
from redis.typing import AbsExpiryT, EncodableT, ExpiryT, KeyT, PatternT

from django_redis import pool
from django_redis.exceptions import CompressorError, ConnectionInterrupted
from django_redis.util import CacheKey

_main_exceptions = (TimeoutError, ResponseError, ConnectionError, socket.timeout)
_main_exceptions = (
RedisConnectionError,
RedisTimeoutError,
ResponseError,
socket.timeout,
)

special_re = re.compile("([*?[])")

Expand Down Expand Up @@ -1001,7 +1008,7 @@ def sscan(

cursor, result = client.sscan(
key,
match=cast(PatternT, self.encode(match)) if match else None,
match=cast("PatternT", self.encode(match)) if match else None,
count=count,
)
return {self.decode(value) for value in result}
Expand All @@ -1024,7 +1031,7 @@ def sscan_iter(
key = self.make_key(key, version=version)
for value in client.sscan_iter(
key,
match=cast(PatternT, self.encode(match)) if match else None,
match=cast("PatternT", self.encode(match)) if match else None,
count=count,
):
yield self.decode(value)
Expand Down
11 changes: 9 additions & 2 deletions django_redis/client/herd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@
from collections import OrderedDict

from django.conf import settings
from redis.exceptions import ConnectionError, ResponseError, TimeoutError
from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import ResponseError
from redis.exceptions import TimeoutError as RedisTimeoutError

from django_redis.client.default import DEFAULT_TIMEOUT, DefaultClient
from django_redis.exceptions import ConnectionInterrupted

_main_exceptions = (ConnectionError, ResponseError, TimeoutError, socket.timeout)
_main_exceptions = (
RedisConnectionError,
RedisTimeoutError,
ResponseError,
socket.timeout,
)


class Marker:
Expand Down
8 changes: 4 additions & 4 deletions django_redis/client/sharded.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Any, Iterator, List, Optional, Set, Union

from redis import Redis
from redis.exceptions import ConnectionError
from redis.exceptions import ConnectionError as RedisConnectionError
from redis.typing import KeyT

from django_redis.client.default import DEFAULT_TIMEOUT, DefaultClient
Expand Down Expand Up @@ -130,7 +130,7 @@ def has_key(self, key, version=None, client=None):
key = self.make_key(key, version=version)
try:
return client.exists(key) == 1
except ConnectionError as e:
except RedisConnectionError as e:
raise ConnectionInterrupted(connection=client) from e

def delete(self, key, version=None, client=None):
Expand Down Expand Up @@ -256,7 +256,7 @@ def incr_version(self, key, delta=1, version=None, client=None):

try:
ttl = self.ttl(old_key, version=version, client=client)
except ConnectionError as e:
except RedisConnectionError as e:
raise ConnectionInterrupted(connection=client) from e

if value is None:
Expand Down Expand Up @@ -296,7 +296,7 @@ def keys(self, search, version=None):
try:
for connection in self._serverdict.values():
keys.extend(connection.keys(pattern))
except ConnectionError as e:
except RedisConnectionError as e:
# FIXME: technically all clients should be passed as `connection`.
client = self.get_server(pattern)
raise ConnectionInterrupted(connection=client) from e
Expand Down
9 changes: 6 additions & 3 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ classifiers =
Framework :: Django :: 4.2
Framework :: Django :: 5.0
Framework :: Django :: 5.1
Framework :: Django :: 5.2
Intended Audience :: Developers
License :: OSI Approved :: BSD License
Operating System :: OS Independent
Expand Down Expand Up @@ -59,10 +60,10 @@ envlist =
mypy
# tests against released versions
py{38,39}-dj{42}-redislatest
py{310,311,312}-dj{42,50,51}-redislatest
py{310,311,312}-dj{42,50,51,52}-redislatest
# tests against unreleased versions
py311-dj51-redismaster
py311-djmain-redis{latest,master}
py312-dj52-redismaster
py312-djmain-redis{latest,master}

[gh-actions]
python =
Expand All @@ -77,6 +78,7 @@ DJANGO =
4.2: dj42
5.0: dj50
5.1: dj51
5.2: dj52
main: djmain
REDIS =
latest: redislatest
Expand All @@ -91,6 +93,7 @@ deps =
dj42: Django>=4.2,<5.0
dj50: Django>=5.0,<5.1
dj51: Django>=5.1,<5.2
dj52: Django>=5.2,<6.0
djmain: https://github.com/django/django/archive/main.tar.gz
msgpack>=0.6.0
pytest
Expand Down
6 changes: 3 additions & 3 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def test_delete_many_generator(self, cache: RedisCache):
assert bool(res) is False

def test_delete_many_empty_generator(self, cache: RedisCache):
res = cache.delete_many(key for key in cast(List[str], []))
res = cache.delete_many(key for key in cast("List[str]", []))
assert bool(res) is False

def test_incr(self, cache: RedisCache):
Expand Down Expand Up @@ -749,7 +749,7 @@ def test_primary_replica_switching(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")

cache = cast(RedisCache, caches["sample"])
cache = cast("RedisCache", caches["sample"])
client = cache.client
client._server = ["foo", "bar"]
client._clients = ["Foo", "Bar"]
Expand All @@ -761,7 +761,7 @@ def test_primary_replica_switching_with_index(self, cache: RedisCache):
if isinstance(cache.client, ShardClient):
pytest.skip("ShardClient doesn't support get_client")

cache = cast(RedisCache, caches["sample"])
cache = cast("RedisCache", caches["sample"])
client = cache.client
client._server = ["foo", "bar"]
client._clients = ["Foo", "Bar"]
Expand Down
12 changes: 6 additions & 6 deletions tests/test_cache_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pytest
from django.core.cache import caches
from pytest import LogCaptureFixture
from redis.exceptions import ConnectionError
from redis.exceptions import ConnectionError as RedisConnectionError

from django_redis.cache import RedisCache
from django_redis.client import ShardClient
Expand All @@ -26,7 +26,7 @@ def ignore_exceptions_cache(settings) -> RedisCache:
settings.CACHES = caches_setting
settings.DJANGO_REDIS_IGNORE_EXCEPTIONS = True
settings.DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
return cast(RedisCache, caches["doesnotexist"])
return cast("RedisCache", caches["doesnotexist"])


def test_get_django_omit_exceptions_many_returns_default_arg(
Expand Down Expand Up @@ -58,7 +58,7 @@ def test_get_django_omit_exceptions_priority_1(settings):
caches_setting["doesnotexist"]["OPTIONS"]["IGNORE_EXCEPTIONS"] = True
settings.CACHES = caches_setting
settings.DJANGO_REDIS_IGNORE_EXCEPTIONS = False
cache = cast(RedisCache, caches["doesnotexist"])
cache = cast("RedisCache", caches["doesnotexist"])
assert cache._ignore_exceptions is True
assert cache.get("key") is None

Expand All @@ -68,9 +68,9 @@ def test_get_django_omit_exceptions_priority_2(settings):
caches_setting["doesnotexist"]["OPTIONS"]["IGNORE_EXCEPTIONS"] = False
settings.CACHES = caches_setting
settings.DJANGO_REDIS_IGNORE_EXCEPTIONS = True
cache = cast(RedisCache, caches["doesnotexist"])
cache = cast("RedisCache", caches["doesnotexist"])
assert cache._ignore_exceptions is False
with pytest.raises(ConnectionError):
with pytest.raises(RedisConnectionError):
cache.get("key")


Expand All @@ -84,7 +84,7 @@ def key_prefix_cache(cache: RedisCache, settings) -> Iterable[RedisCache]:

@pytest.fixture
def with_prefix_cache() -> Iterable[RedisCache]:
with_prefix = cast(RedisCache, caches["with_prefix"])
with_prefix = cast("RedisCache", caches["with_prefix"])
yield with_prefix
with_prefix.clear()

Expand Down
Loading