Skip to content

Commit c44b96e

Browse files
authored
Merge pull request #105 from voyc-jean/fix-django-6-incompatibility
Add Django 6 compatibility and modernise codebase
2 parents 45d3776 + 9bd9424 commit c44b96e

31 files changed

Lines changed: 197 additions & 160 deletions

.github/workflows/test.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111
jobs:
1212
tests:
1313
name: "Python ${{ matrix.python-version }}"
14-
runs-on: "ubuntu-20.04"
14+
runs-on: "ubuntu-latest"
1515
services:
1616
redis:
1717
image: redis
@@ -24,17 +24,17 @@ jobs:
2424
- 6379:6379
2525
strategy:
2626
matrix:
27-
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
27+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
2828
steps:
29-
- uses: "actions/checkout@v2"
30-
- uses: "actions/setup-python@v2"
29+
- uses: "actions/checkout@v6"
30+
- uses: "actions/setup-python@v6"
3131
with:
3232
python-version: "${{ matrix.python-version }}"
3333
- name: "Install dependencies"
3434
run: |
3535
set -xe
3636
python -m pip install --upgrade pip setuptools
37-
python -m pip install --upgrade poetry tox tox-gh-actions
37+
python -m pip install --upgrade poetry tox tox-gh-actions poetry-plugin-export
3838
3939
- name: "Run tox targets for ${{ matrix.python-version }}"
4040
run: "python -m tox"

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
.vagrant
21
sandbox/db.sqlite3
32
docs/_build
43
dist/*

.python-version

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
3.8.5
2-
3.7.8
3-
3.6.11
1+
3.10.19
2+
3.11.14
3+
3.12.12
4+
3.13.11
5+
3.14.2

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ build:
22
image: latest
33

44
python:
5-
version: 3.8
5+
version: 3.14
66
pip_install: true
77
extra_requirements:
88
- docs

CHANGELOG.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
Changelog
33
=========
44

5+
4.0.0
6+
~~~~~
7+
8+
* BREAKING CHANGE: Drop support for Django < 5.2 and Python < 3.10.
9+
* BREAKING CHANGE: Drop support for Celery < 5.0.
10+
* BREAKING CHANGE: Drop support for django-rq < 3.0.
11+
* Add support for Django 5.2.
12+
* Add support for Django 6.0.
13+
* Modernise Python code.
14+
515
3.0.0
616
~~~~~
717

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Yup - `over on readthedocs.org`_.
3636
Supported versions
3737
------------------
3838

39-
Python 3.6+ is supported. Django 2.2+ is supported.
39+
Python 3.10+ is supported. Django 5.2+ is supported.
4040

4141

4242
Do you have tests?

Vagrantfile

Lines changed: 0 additions & 8 deletions
This file was deleted.

cacheback/__init__.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
try:
2-
import importlib.metadata as importlib_metadata
3-
except ModuleNotFoundError:
4-
# This is required for Python versions < 3.8
5-
import importlib_metadata
1+
import importlib.metadata as importlib_metadata
2+
63

74
try:
85
__version__ = importlib_metadata.version('django-cacheback')

cacheback/base.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from django.conf import settings
77
from django.core.cache import DEFAULT_CACHE_ALIAS, caches
88
from django.db.models import Model as DjangoModel
9-
from django.utils.itercompat import is_iterable
109

1110
from .utils import enqueue_task, get_job_class
1211

@@ -29,15 +28,15 @@ def to_bytestring(value):
2928
:returns: a bytestring
3029
"""
3130
if isinstance(value, DjangoModel):
32-
return ('%s:%s' % (value.__class__, hash(value))).encode('utf-8')
31+
return (f'{value.__class__}:{hash(value)}').encode('utf-8')
3332
if isinstance(value, str):
3433
return value.encode('utf8')
3534
if isinstance(value, bytes):
3635
return value
3736
return bytes(str(value), 'utf8')
3837

3938

40-
class Job(object):
39+
class Job:
4140
"""
4241
A cached read job.
4342
@@ -59,7 +58,7 @@ class Job(object):
5958
#: refresh the cache.
6059
refresh_timeout = 60
6160

62-
#: Secifies which cache to use from your `CACHES` setting. It defaults to
61+
#: Specifies which cache to use from your `CACHES` setting. It defaults to
6362
#: `default`.
6463
cache_alias = None
6564

@@ -91,7 +90,7 @@ class Job(object):
9190

9291
@property
9392
def class_path(self):
94-
return '%s.%s' % (self.__module__, self.__class__.__name__)
93+
return f'{self.__module__}.{self.__class__.__name__}'
9594

9695
def __init__(self):
9796
self.cache_alias = self.cache_alias or getattr(
@@ -399,11 +398,11 @@ def key(self, *args, **kwargs):
399398
return self.class_path
400399
try:
401400
if args and not kwargs:
402-
return "%s:%s" % (self.class_path, self.hash(args))
401+
return f"{self.class_path}:{self.hash(args)}"
403402
# The line might break if your passed values are un-hashable. If
404403
# it does, you need to override this method and implement your own
405404
# key algorithm.
406-
return "%s:%s:%s:%s" % (
405+
return "{}:{}:{}:{}".format(
407406
self.class_path,
408407
self.hash(args),
409408
self.hash([k for k in sorted(kwargs)]),
@@ -422,7 +421,7 @@ def hash(self, value):
422421
423422
This is for use in a cache key.
424423
"""
425-
if is_iterable(value):
424+
if isinstance(value, collections.abc.Iterable):
426425
value = tuple(to_bytestring(v) for v in value)
427426
return hashlib.md5(b':'.join(value)).hexdigest()
428427

@@ -440,7 +439,7 @@ def process_result(self, result, call, cache_status, sync_fetch=None):
440439
:param result: The result to be returned
441440
:param call: A named tuple with properties 'args' and 'kwargs that
442441
holds the call args and kwargs
443-
:param cache_status: A status integrer, accessible as class constants
442+
:param cache_status: A status integer, accessible as class constants
444443
self.MISS, self.HIT, self.STALE
445444
:param sync_fetch: A boolean indicating whether a synchronous fetch was
446445
performed. A value of None indicates that no fetch

cacheback/jobs.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
try:
2-
import importlib
3-
except ImportError:
4-
import django.utils.importlib as importlib
1+
import importlib
52

63
from .base import Job
74

@@ -19,7 +16,7 @@ def __init__(
1916
task_options=None,
2017
set_data_kwarg=None,
2118
):
22-
super(FunctionJob, self).__init__()
19+
super().__init__()
2320
if lifetime is not None:
2421
self.lifetime = int(lifetime)
2522
if fetch_on_miss is not None:
@@ -43,7 +40,7 @@ def get_init_kwargs(self):
4340
def prepare_args(self, fn, *args):
4441
# Convert function into "module:name" form so that is can be pickled and
4542
# then re-imported.
46-
return ("%s:%s" % (fn.__module__, fn.__name__),) + args
43+
return (f"{fn.__module__}:{fn.__name__}",) + args
4744

4845
def fetch(self, fn_string, *args, **kwargs):
4946
# Import function from string representation
@@ -67,7 +64,7 @@ def __init__(
6764
"""
6865
:model: The model class to use
6966
"""
70-
super(QuerySetJob, self).__init__()
67+
super().__init__()
7168
self.model = model
7269
if lifetime is not None:
7370
self.lifetime = lifetime
@@ -82,7 +79,7 @@ def get_init_kwargs(self):
8279
return {'model': self.model, 'lifetime': self.lifetime, 'cache_alias': self.cache_alias}
8380

8481
def key(self, *args, **kwargs):
85-
return "%s-%s" % (self.model.__name__, super(QuerySetJob, self).key(*args, **kwargs))
82+
return f"{self.model.__name__}-{super().key(*args, **kwargs)}"
8683

8784

8885
class QuerySetGetJob(QuerySetJob):

0 commit comments

Comments
 (0)