From 75cc8ce60dac3784c07ce9af5d916193ab2e9762 Mon Sep 17 00:00:00 2001 From: Anders <6058745+ddabble@users.noreply.github.com> Date: Wed, 15 May 2024 21:50:17 +0200 Subject: [PATCH] Dropped support for Django 3.2 Its EOL was passed last month (April 1st); see https://www.djangoproject.com/download/#supported-versions. The changes in `test_admin.py` were made to slightly reduce the amount of work required when dropping support for Django 4.2 in the future (also the previous comments contained a typo, and should have said "prior to Django 5.0" instead of "prior to Django 4.2"). --- .github/workflows/test.yml | 10 +----- CHANGES.rst | 3 ++ README.rst | 1 - docs/index.rst | 1 - requirements/postgres.txt | 5 +-- requirements/test.txt | 2 -- runtests.py | 16 ++++------ setup.py | 4 +-- simple_history/tests/tests/test_admin.py | 36 +++++++++++++--------- simple_history/tests/tests/test_manager.py | 15 --------- tox.ini | 5 +-- 11 files changed, 34 insertions(+), 64 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 575ab7ac0..ad2a9b134 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: fail-fast: false matrix: python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13-dev'] - django-version: ['3.2', '4.2', '5.0', 'main'] + django-version: ['4.2', '5.0', 'main'] exclude: # Exclude py3.8 and py3.9 for Django main and 5.0 @@ -25,14 +25,6 @@ jobs: - python-version: '3.9' django-version: 'main' - # Exclude py3.11, py3.12 and py3.13 for Django 3.2 - - python-version: '3.11' - django-version: '3.2' - - python-version: '3.12' - django-version: '3.2' - - python-version: '3.13-dev' - django-version: '3.2' - services: postgres: diff --git a/CHANGES.rst b/CHANGES.rst index b4db1abfe..3766fad38 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changes Unreleased ---------- +- Dropped support for Django 3.2, which reached end-of-life on 2024-04-01 (gh-1344) +- Removed the temporary requirement on ``asgiref>=3.6`` added in 3.5.0, + now that the minimum required Django version is 4.2 (gh-1344) 3.6.0 (2024-05-26) ------------------ diff --git a/README.rst b/README.rst index c8442f686..79b1ec075 100644 --- a/README.rst +++ b/README.rst @@ -41,7 +41,6 @@ This app supports the following combinations of Django and Python: ========== ======================== Django Python ========== ======================== -3.2 3.8, 3.9, 3.10 4.2 3.8, 3.9, 3.10, 3.11, 3.12, 3.13-dev 5.0 3.10, 3.11, 3.12, 3.13-dev main 3.10, 3.11, 3.12, 3.13-dev diff --git a/docs/index.rst b/docs/index.rst index e6eaaf749..2276ba9f6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,7 +41,6 @@ This app supports the following combinations of Django and Python: ========== ======================= Django Python ========== ======================= -3.2 3.8, 3.9, 3.10 4.2 3.8, 3.9, 3.10, 3.11, 3.12, 3.13-dev 5.0 3.10, 3.11, 3.12, 3.13-dev main 3.10, 3.11, 3.12, 3.13-dev diff --git a/requirements/postgres.txt b/requirements/postgres.txt index aaa87fe1b..d240df452 100644 --- a/requirements/postgres.txt +++ b/requirements/postgres.txt @@ -1,4 +1 @@ -# DEV: Replace this with `psycopg[binary]` when the minimum required Django version is -# 4.2 or higher, as this is likely to be deprecated in the future -# (see https://docs.djangoproject.com/en/4.2/releases/4.2/#psycopg-3-support) -psycopg2-binary==2.9.9 +psycopg[binary]==3.1.19 diff --git a/requirements/test.txt b/requirements/test.txt index 0b7414dc3..ae6ed25c0 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,3 +1 @@ -r ./coverage.txt -# DEV: Remove this requirement entirely when the minimum required Django version is 4.2 -asgiref>=3.6 diff --git a/runtests.py b/runtests.py index 62ebbef79..de2e9c194 100755 --- a/runtests.py +++ b/runtests.py @@ -135,6 +135,12 @@ def __getitem__(self, item): }, } ], + STORAGES={ + "default": { + # Speeds up tests and prevents locally storing files created through them + "BACKEND": "django.core.files.storage.InMemoryStorage", + }, + }, DEFAULT_AUTO_FIELD="django.db.models.AutoField", USE_TZ=False, ) @@ -146,16 +152,6 @@ def __getitem__(self, item): DEFAULT_SETTINGS["MIDDLEWARE"] = MIDDLEWARE -# DEV: Merge these settings into DEFAULT_SETTINGS when the minimum required -# Django version is 4.2 or higher -if django.VERSION >= (4, 2): - DEFAULT_SETTINGS["STORAGES"] = { - "default": { - # Speeds up tests and prevents locally storing files created through them - "BACKEND": "django.core.files.storage.InMemoryStorage", - }, - } - def get_default_settings(*, database_name=DEFAULT_DATABASE_NAME): return { diff --git a/setup.py b/setup.py index 8e1909d60..cf90376a4 100644 --- a/setup.py +++ b/setup.py @@ -11,8 +11,7 @@ "fallback_version": "0.0.0", }, setup_requires=["setuptools_scm"], - # DEV: Remove `asgiref` when the minimum required Django version is 4.2 - install_requires=["asgiref>=3.6"], + install_requires=[], description="Store model history and view/revert changes from admin site.", long_description="\n".join((readme.read(), changes.read())), long_description_content_type="text/x-rst", @@ -38,7 +37,6 @@ "Environment :: Web Environment", "Intended Audience :: Developers", "Framework :: Django", - "Framework :: Django :: 3.2", "Framework :: Django :: 4.2", "Framework :: Django :: 5.0", "Programming Language :: Python", diff --git a/simple_history/tests/tests/test_admin.py b/simple_history/tests/tests/test_admin.py index 02b5bdc52..d85e51a54 100644 --- a/simple_history/tests/tests/test_admin.py +++ b/simple_history/tests/tests/test_admin.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta from unittest.mock import ANY, patch +import django from django.contrib.admin import AdminSite from django.contrib.admin.utils import quote from django.contrib.auth import get_user_model @@ -621,6 +622,7 @@ def test_history_form_view_without_getting_history(self): context = { **admin_site.each_context(request), # Verify this is set for original object + "log_entries": ANY, "original": poll, "change_history": False, "title": "Revert %s" % force_str(poll), @@ -650,9 +652,9 @@ def test_history_form_view_without_getting_history(self): "save_on_top": admin.save_on_top, "root_path": getattr(admin_site, "root_path", None), } - # This key didn't exist prior to Django 4.2 - if "log_entries" in context: - context["log_entries"] = ANY + # DEV: Remove this when support for Django 4.2 has been dropped + if django.VERSION < (5, 0): + del context["log_entries"] mock_render.assert_called_once_with( request, admin.object_history_form_template, context @@ -680,6 +682,7 @@ def test_history_form_view_getting_history(self): context = { **admin_site.each_context(request), # Verify this is set for history object not poll object + "log_entries": ANY, "original": history.instance, "change_history": True, "title": "Revert %s" % force_str(history.instance), @@ -709,9 +712,9 @@ def test_history_form_view_getting_history(self): "save_on_top": admin.save_on_top, "root_path": getattr(admin_site, "root_path", None), } - # This key didn't exist prior to Django 4.2 - if "log_entries" in context: - context["log_entries"] = ANY + # DEV: Remove this when support for Django 4.2 has been dropped + if django.VERSION < (5, 0): + del context["log_entries"] mock_render.assert_called_once_with( request, admin.object_history_form_template, context @@ -739,6 +742,7 @@ def test_history_form_view_getting_history_with_setting_off(self): context = { **admin_site.each_context(request), # Verify this is set for history object not poll object + "log_entries": ANY, "original": poll, "change_history": False, "title": "Revert %s" % force_str(poll), @@ -768,9 +772,9 @@ def test_history_form_view_getting_history_with_setting_off(self): "save_on_top": admin.save_on_top, "root_path": getattr(admin_site, "root_path", None), } - # This key didn't exist prior to Django 4.2 - if "log_entries" in context: - context["log_entries"] = ANY + # DEV: Remove this when support for Django 4.2 has been dropped + if django.VERSION < (5, 0): + del context["log_entries"] mock_render.assert_called_once_with( request, admin.object_history_form_template, context @@ -798,6 +802,7 @@ def test_history_form_view_getting_history_abstract_external(self): context = { **admin_site.each_context(request), # Verify this is set for history object + "log_entries": ANY, "original": history.instance, "change_history": True, "title": "Revert %s" % force_str(history.instance), @@ -829,9 +834,9 @@ def test_history_form_view_getting_history_abstract_external(self): "save_on_top": admin.save_on_top, "root_path": getattr(admin_site, "root_path", None), } - # This key didn't exist prior to Django 4.2 - if "log_entries" in context: - context["log_entries"] = ANY + # DEV: Remove this when support for Django 4.2 has been dropped + if django.VERSION < (5, 0): + del context["log_entries"] mock_render.assert_called_once_with( request, admin.object_history_form_template, context @@ -862,6 +867,7 @@ def test_history_form_view_accepts_additional_context(self): context = { **admin_site.each_context(request), # Verify this is set for original object + "log_entries": ANY, "anything_else": "will be merged into context", "original": poll, "change_history": False, @@ -892,9 +898,9 @@ def test_history_form_view_accepts_additional_context(self): "save_on_top": admin.save_on_top, "root_path": getattr(admin_site, "root_path", None), } - # This key didn't exist prior to Django 4.2 - if "log_entries" in context: - context["log_entries"] = ANY + # DEV: Remove this when support for Django 4.2 has been dropped + if django.VERSION < (5, 0): + del context["log_entries"] mock_render.assert_called_once_with( request, admin.object_history_form_template, context diff --git a/simple_history/tests/tests/test_manager.py b/simple_history/tests/tests/test_manager.py index a10eda51c..75bf94a78 100644 --- a/simple_history/tests/tests/test_manager.py +++ b/simple_history/tests/tests/test_manager.py @@ -1,7 +1,6 @@ from datetime import datetime, timedelta from operator import attrgetter -import django from django.contrib.auth import get_user_model from django.db import IntegrityError from django.test import TestCase, override_settings, skipUnlessDBFeature @@ -199,13 +198,6 @@ def setUp(self): Poll(id=4, question="Question 4", pub_date=datetime.now()), ] - # DEV: Remove this method when the minimum required Django version is 4.2 - def assertQuerySetEqual(self, *args, **kwargs): - if django.VERSION < (4, 2): - return self.assertQuerysetEqual(*args, **kwargs) - else: - return super().assertQuerySetEqual(*args, **kwargs) - def test_simple_bulk_history_create(self): created = Poll.history.bulk_history_create(self.data) self.assertEqual(len(created), 4) @@ -334,13 +326,6 @@ def setUp(self): Poll(id=4, question="Question 4", pub_date=datetime.now()), ] - # DEV: Remove this method when the minimum required Django version is 4.2 - def assertQuerySetEqual(self, *args, **kwargs): - if django.VERSION < (4, 2): - return self.assertQuerysetEqual(*args, **kwargs) - else: - return super().assertQuerySetEqual(*args, **kwargs) - def test_simple_bulk_history_create(self): created = Poll.history.bulk_history_create(self.data, update=True) self.assertEqual(len(created), 4) diff --git a/tox.ini b/tox.ini index dc692c674..e5b11214a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,11 +1,10 @@ [tox] envlist = - py{38,39,310}-dj32-{sqlite3,postgres,mysql,mariadb}, py{38,39,310,311,312}-dj42-{sqlite3,postgres,mysql,mariadb}, py{310,311,312}-dj50-{sqlite3,postgres,mysql,mariadb}, py{310,311,312}-djmain-{sqlite3,postgres,mysql,mariadb}, # DEV: Add `313` to the Python versions above (so that postgres is tested with 3.13) - # when `psycopg2-binary` supports 3.13 + # when `psycopg` provides binaries for 3.13 py313-dj{42,50,main}-{sqlite3,mysql,mariadb}, docs, lint @@ -21,7 +20,6 @@ python = [gh-actions:env] DJANGO = - 3.2: dj32 4.2: dj42 5.0: dj50 main: djmain @@ -35,7 +33,6 @@ exclude = __init__.py,simple_history/registry_tests/migration_test_app/migration [testenv] deps = -rrequirements/test.txt - dj32: Django>=3.2,<3.3 dj42: Django>=4.2,<4.3 dj50: Django>=5.0,<5.1 djmain: https://github.com/django/django/tarball/main