From e4c939e634cf2cc54f4c0d5fbbad690bdf359c1c Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 08:47:50 +0100
Subject: [PATCH 1/6] Add Django 5 and Python 3.12 to test matrix

---
 .github/workflows/ci.yml | 8 ++++++--
 README.md                | 4 ++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bbd0ea7..0b5155c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,13 +9,17 @@ jobs:
 
     strategy:
       matrix:
-        python: ["3.8", "3.9", "3.10", "3.11"]
-        django: ["3.2", "4.0", "4.1", "4.2"]
+        python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
+        django: ["3.2", "4.0", "4.1", "4.2", "5.0"]
         exclude:
           - python: "3.11"
             django: "3.2"
+          - python: "3.12"
+            django: "3.2"
           - python: "3.11"
             django: "4.0"
+          - python: "3.12"
+            django: "4.0"
         database_url:
           - postgres://runner:password@localhost/project
           - mysql://root:root@127.0.0.1/project
diff --git a/README.md b/README.md
index d814caa..e78b62f 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,8 @@ Simple database-backed job queue. Jobs are defined in your settings, and are pro
 Asynchronous tasks are run via a *job queue*. This system is designed to support multi-step job workflows.
 
 Supported and tested against:
-- Django 3.2, 4.0, 4.1, 4.2
-- Python 3.8, 3.9, 3.10, 3.11
+- Django 3.2, 4.0, 4.1, 4.2, 5.0
+- Python 3.8, 3.9, 3.10, 3.11, 3.12
 
 ## Getting Started
 

From 705dc4b2cd1186ba4dd82c0cebb4b0c3e395119e Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 08:48:20 +0100
Subject: [PATCH 2/6] Unpin postgres version

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0b5155c..acb2a03 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -27,7 +27,7 @@ jobs:
 
     services:
       postgres:
-        image: postgres:12
+        image: postgres
         ports:
           - 5432:5432
         env:

From 8d88eb2fef3b3a4e6936517079a6aef53368dfe4 Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 09:22:48 +0100
Subject: [PATCH 3/6] Fix timezone issues

---
 django_dbq/tests.py | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/django_dbq/tests.py b/django_dbq/tests.py
index 3ae7ab9..5ded5d7 100644
--- a/django_dbq/tests.py
+++ b/django_dbq/tests.py
@@ -13,6 +13,13 @@
 from io import StringIO
 
 
+try:
+    utc = timezone.utc
+except AttributeError:
+    from datetime import timezone as datetime_timezone
+    utc = datetime_timezone.utc
+
+
 def test_task(job=None):
     pass  # pragma: no cover
 
@@ -189,7 +196,7 @@ def test_get_next_ready_job(self):
         Job.objects.create(name="testjob", state=Job.STATES.READY)
         Job.objects.create(name="testjob", state=Job.STATES.PROCESSING)
         expected = Job.objects.create(name="testjob", state=Job.STATES.READY)
-        expected.created = datetime.now() - timedelta(minutes=1)
+        expected.created = timezone.now() - timedelta(minutes=1)
         expected.save()
 
         self.assertEqual(Job.objects.get_ready_or_none("default"), expected)
@@ -231,7 +238,7 @@ def test_gets_jobs_in_priority_and_date_order(self):
 
     def test_ignores_jobs_until_run_after_is_in_the_past(self):
         job_1 = Job.objects.create(name="testjob")
-        job_2 = Job.objects.create(name="testjob", run_after=datetime(2021, 11, 4, 8))
+        job_2 = Job.objects.create(name="testjob", run_after=datetime(2021, 11, 4, 8, tzinfo=utc))
 
         with freezegun.freeze_time(datetime(2021, 11, 4, 7)):
             self.assertEqual(
@@ -256,7 +263,7 @@ def test_get_next_ready_job_created(self):
         Job.objects.create(name="testjob", state=Job.STATES.NEW)
         Job.objects.create(name="testjob", state=Job.STATES.PROCESSING)
         expected = Job.objects.create(name="testjob", state=Job.STATES.NEW)
-        expected.created = datetime.now() - timedelta(minutes=1)
+        expected.created = timezone.now() - timedelta(minutes=1)
         expected.save()
 
         self.assertEqual(Job.objects.get_ready_or_none("default"), expected)
@@ -336,7 +343,7 @@ def test_failure_hook(self):
 @override_settings(JOBS={"testjob": {"tasks": ["a"]}})
 class DeleteOldJobsTestCase(TestCase):
     def test_delete_old_jobs(self):
-        two_days_ago = datetime.utcnow() - timedelta(days=2)
+        two_days_ago = timezone.now() - timedelta(days=2)
 
         j1 = Job.objects.create(name="testjob", state=Job.STATES.COMPLETE)
         j1.created = two_days_ago

From 8d5e7f637c80e3e8f373f397a4dab5c2ff9bf48b Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 09:25:03 +0100
Subject: [PATCH 4/6] Exclude unsupported Python/Django version combinations

---
 .github/workflows/ci.yml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index acb2a03..5c2a216 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,6 +20,10 @@ jobs:
             django: "4.0"
           - python: "3.12"
             django: "4.0"
+          - python: "3.8"
+            django: "5.0"
+          - python: "3.9"
+            django: "5.0"
         database_url:
           - postgres://runner:password@localhost/project
           - mysql://root:root@127.0.0.1/project

From c12e62d176eff86aff9e1d30941d320a0db41b35 Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 09:27:05 +0100
Subject: [PATCH 5/6] Set USE_TZ to True in test settings

---
 testsettings.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/testsettings.py b/testsettings.py
index 040eade..2d0d0ba 100644
--- a/testsettings.py
+++ b/testsettings.py
@@ -19,3 +19,5 @@
     "root": {"handlers": ["console"], "level": "INFO",},
     "loggers": {"django_dbq": {"level": "CRITICAL", "propagate": True,},},
 }
+
+USE_TZ = True

From 90f48fe4c142da458b5d81949ec6b664095832b6 Mon Sep 17 00:00:00 2001
From: Jamie Matthews <jamie@dabapps.com>
Date: Tue, 9 Apr 2024 09:27:48 +0100
Subject: [PATCH 6/6] Black formatting

---
 django_dbq/tests.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/django_dbq/tests.py b/django_dbq/tests.py
index 5ded5d7..5ed868c 100644
--- a/django_dbq/tests.py
+++ b/django_dbq/tests.py
@@ -17,6 +17,7 @@
     utc = timezone.utc
 except AttributeError:
     from datetime import timezone as datetime_timezone
+
     utc = datetime_timezone.utc
 
 
@@ -238,7 +239,9 @@ def test_gets_jobs_in_priority_and_date_order(self):
 
     def test_ignores_jobs_until_run_after_is_in_the_past(self):
         job_1 = Job.objects.create(name="testjob")
-        job_2 = Job.objects.create(name="testjob", run_after=datetime(2021, 11, 4, 8, tzinfo=utc))
+        job_2 = Job.objects.create(
+            name="testjob", run_after=datetime(2021, 11, 4, 8, tzinfo=utc)
+        )
 
         with freezegun.freeze_time(datetime(2021, 11, 4, 7)):
             self.assertEqual(