Repository: Dunedan/django-lockdown
Pull request #21: Update support for Django to 4.2 - 5.1 and for Python 3.9 - 3.13
Author: login: browniebroke
Created: 2024-02-21T09:12:36Z | Merged: 2025-03-28T09:11:56Z

Update official support matrix for Django and Python versions to match upstream support. 

FWIW, we already use this package with ~Python 3.11 and Django 4.2~ Python 3.12 and Django 5.1, but I thought it was worth updating official support on CI.

--- 

Thanks a lot for opening a pull request. :tada:

To ensure your pull request can get merged as fast as possible, please check
all points in the following list:

- [x] When adding new code add corresponding tests as well.
- [x] Ensure your code follows the [Python Style Guide (PEP8)][1] and the
      [Docstring Conventions (PEP257)][2].
- [x] Update the `AUTHORS.rst`, `CHANGES.rst` and `README.rst` as necessary.
- [x] Check that [continuous integration (CI)][1] runs succeed after you opened
      the pull request and fix the issues it detects.

Please also replace this template with a description of your changes before you
open the pull request.

[1]: https://www.python.org/dev/peps/pep-0008/
[2]: https://www.python.org/dev/peps/pep-0257/
[3]: https://github.com/Dunedan/django-lockdown/actions



Diff:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 40b97a3..a72b371 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -5,23 +5,33 @@ on:
   - pull_request
 jobs:
   test:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     strategy:
       fail-fast: false
       matrix:
         python-version:
-          - 3.6
-          - 3.7
-          - 3.8
-          - 3.9
-          - pypy3
+          - "3.9"
+          - "3.10"
+          - "3.11"
+          - "3.12"
+          - "3.13"
+          - "pypy3.10"
         django-version:
-          - Django>=2.2,<3.0
-          - Django>=3.0,<3.1
-          - Django>=3.1,<3.2
+          - Django>=4.2,<5.0
+          - Django>=5.0,<5.1
+          - Django>=5.1,<5.2
+        exclude:
+          - python-version: "3.9"
+            django-version: "Django>=5.0,<5.1"
+          - python-version: "3.9"
+            django-version: "Django>=5.1,<5.2"
+          - python-version: "3.13"
+            django-version: "Django>=4.2,<5.0"
+          - python-version: "3.13"
+            django-version: "Django>=5.0,<5.1"
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-python@v2
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Django
@@ -35,10 +45,10 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
   pre-commit:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-python@v2
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v5
         with:
-          python-version: 3.9
-      - uses: pre-commit/action@v2.0.0
+          python-version: "3.11"
+      - uses: pre-commit/action@v3.0.1
diff --git a/CHANGES.rst b/CHANGES.rst
index fe7cb8f..4eef4aa 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,14 @@ CHANGES
 Unreleased
 ----------
 
+- Remove support for end-of-life Django versions (from 2.2 until 4.1).
+
+- Remove support for end-of-life Python versions (3.6, 3.7 and 3.8).
+
+- Add support for Django 3.2, 4.0, 4.1, 4.2, 5.0 and 5.1.
+
+- Add support for Python 3.10, 3.11, 3.12 and 3.13.
+
 - Updated pre-commit hooks and modernize code style. Most notably started to
   use f-strings.
 
diff --git a/README.rst b/README.rst
index f4c9a98..716c76a 100644
--- a/README.rst
+++ b/README.rst
@@ -43,9 +43,9 @@ the `LOCKDOWN_FORM`_ setting.
 Dependencies
 ------------
 
-``django-lockdown`` requires `Python`_ 3.6 or later and `Django`_ 2.2 or later.
+``django-lockdown`` requires `Python`_ 3.9 or later and `Django`_ 4.2 or later.
 
-As an alternative to CPython `PyPy`_ 3.5 and 3.6 are supported as well.
+As an alternative to CPython `PyPy`_ 3.10 is supported as well.
 
 .. _Python: https://www.python.org/
 .. _Django: https://www.djangoproject.com/
diff --git a/lockdown/tests/urls.py b/lockdown/tests/urls.py
index f8d1a3a..c75c0f0 100644
--- a/lockdown/tests/urls.py
+++ b/lockdown/tests/urls.py
@@ -1,29 +1,36 @@
-from django.conf.urls import url
+from django.urls import path, re_path
 
 from . import views
 
 urlpatterns = [
-    url(r'^a/view/$', views.a_view),
-    url(r'^locked/view/$', views.locked_view),
-    url(r'^overridden/locked/view/$', views.overridden_locked_view),
-    url(r'^locked/view/with/exception1/', views.locked_view_with_exception),
-    url(r'^locked/view/with/exception2/', views.locked_view_with_exception),
-    url(r'^locked/view/with/ip_exception/',
-        views.locked_view_with_ip_exception),
-    url(r'^locked/view/with/ip_exception_ipv6/',
-        views.locked_view_with_ip_exception_ipv6),
-    url(r'^locked/view/with/ip_exception_subnet/',
-        views.locked_view_with_ip_exception_subnet),
-    url(r'^locked/view/with/ip_exception_ipv6_subnet/',
-        views.locked_view_with_ip_exception_ipv6_subnet),
-    url(r'^locked/view/with/extra/context/',
-        views.locked_view_with_extra_context),
-    url(r'^locked/view/until/yesterday/', views.locked_view_until_yesterday),
-    url(r'^locked/view/until/tomorrow/', views.locked_view_until_tomorrow),
-    url(r'^locked/view/after/yesterday/', views.locked_view_after_yesterday),
-    url(r'^locked/view/after/tomorrow/', views.locked_view_after_tomorrow),
-    url(r'^locked/view/until/and/after/', views.locked_view_until_and_after),
-    url(r'^auth/user/locked/view/$', views.user_locked_view),
-    url(r'^auth/staff/locked/view/$', views.staff_locked_view),
-    url(r'^auth/superuser/locked/view/$', views.superuser_locked_view),
+    path('a/view/', views.a_view),
+    path('locked/view/', views.locked_view),
+    path('overridden/locked/view/', views.overridden_locked_view),
+    re_path(r'^locked/view/with/exception1/',
+            views.locked_view_with_exception),
+    re_path(r'^locked/view/with/exception2/',
+            views.locked_view_with_exception),
+    re_path(r'^locked/view/with/ip_exception/',
+            views.locked_view_with_ip_exception),
+    re_path(r'^locked/view/with/ip_exception_ipv6/',
+            views.locked_view_with_ip_exception_ipv6),
+    re_path(r'^locked/view/with/ip_exception_subnet/',
+            views.locked_view_with_ip_exception_subnet),
+    re_path(r'^locked/view/with/ip_exception_ipv6_subnet/',
+            views.locked_view_with_ip_exception_ipv6_subnet),
+    re_path(r'^locked/view/with/extra/context/',
+            views.locked_view_with_extra_context),
+    re_path(r'^locked/view/until/yesterday/',
+            views.locked_view_until_yesterday),
+    re_path(r'^locked/view/until/tomorrow/',
+            views.locked_view_until_tomorrow),
+    re_path(r'^locked/view/after/yesterday/',
+            views.locked_view_after_yesterday),
+    re_path(r'^locked/view/after/tomorrow/',
+            views.locked_view_after_tomorrow),
+    re_path(r'^locked/view/until/and/after/',
+            views.locked_view_until_and_after),
+    path('auth/user/locked/view/', views.user_locked_view),
+    path('auth/staff/locked/view/', views.staff_locked_view),
+    path('auth/superuser/locked/view/', views.superuser_locked_view),
 ]
diff --git a/setup.py b/setup.py
index caa95ae..df21ab1 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,8 @@
     maintainer_email='danielroschka@phoenitydawn.de',
     url='https://github.com/Dunedan/django-lockdown/',
     packages=find_packages(exclude=['lockdown.tests']),
-    install_requires=['Django>=2.2'],
+    python_requires='>=3.9',
+    install_requires=['Django>=4.2'],
     classifiers=[
         'Development Status :: 5 - Production/Stable',
         'Environment :: Web Environment',
@@ -25,16 +26,17 @@
         'License :: OSI Approved :: BSD License',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 3.6',
-        'Programming Language :: Python :: 3.7',
-        'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.10',
+        'Programming Language :: Python :: 3.11',
+        'Programming Language :: Python :: 3.12',
+        'Programming Language :: Python :: 3.13',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
         'Framework :: Django',
-        'Framework :: Django :: 2.2',
-        'Framework :: Django :: 3.0',
-        'Framework :: Django :: 3.1',
+        'Framework :: Django :: 4.2',
+        'Framework :: Django :: 5.0',
+        'Framework :: Django :: 5.1',
     ],
     zip_safe=False,
     test_suite='runtests.runtests',


Reviews:
user: login: Dunedan
body: Hi @browniebroke,

Thanks a lot for this contribution. As long as there are users of django-lockdown, I'm interested in keeping it maintained. Unfortunately I entirely missed this PR when you opened it, so thanks for the heads up.

I have a bunch of comments, but I believe we can get fix them fairly quickly.

> Since that was open, Django 5.1 and Python 3.13 were released, Python 3.8 went EOL and Django 5.2 is just around the corner.

My policy has always been to only support versions of Python and Django which aren't EOL. I'd appreciate if you'd remove support for Python 3.8 and Django <4.2 as well.
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-03-25T07:24:03Z
user: login: browniebroke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T09:23:15Z
user: login: browniebroke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T09:23:55Z
user: login: browniebroke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T09:24:08Z
user: login: browniebroke
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T10:17:09Z
user: login: Dunedan
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-25T14:10:41Z

Review comments:
diff_hunk: @@ -16,49 +18,53 @@ repos:
           - --allow-missing-credentials
       - id: detect-private-key
 
-  - repo: git://github.com/adrienverge/yamllint
-    rev: v1.25.0
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.35.1
     hooks:
       - id: yamllint
         args:
           - -s
 
-  - repo: git://github.com/PyCQA/isort
-    rev: 5.6.4
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.13.2
     hooks:
       - id: isort
         args:
           - --check-only
           - --diff
 
-  - repo: git://github.com/PyCQA/prospector/
-    rev: 1.3.1
-    hooks:
-      - id: prospector
-        additional_dependencies:
-          - django
-          - ipaddress
-          - prospector
+  # This hook fails with the following error
+  # `pylint: failure / Tool pylint failed to run (exception was raised)`
+  # It's an old version which needs more work to be brought up to date
+  # - repo: https://github.com/PyCQA/prospector/
+  #   rev: 1.3.1
+  #   hooks:
+  #     - id: prospector
+  #       additional_dependencies:
+  #         - django
+  #         - ipaddress
+  #         - prospector
+  #         - setuptools
path: .pre-commit-config.yaml
user: login: Dunedan
body: Updating prospector to the latest version works for me:

```suggestion
  - repo: https://github.com/prospector-dev/prospector/
    rev: v1.16.0
    hooks:
      - id: prospector
        additional_dependencies:
          - django
```

pylint complains about some code quality rules afterwards, but those should be fixable.
created_at: 2025-03-25T07:12:10Z
author_association: OWNER
diff_hunk: @@ -1,7 +1,9 @@
 ---
+default_language_version:
+  python: python3.11
path: .pre-commit-config.yaml
user: login: Dunedan
body: I'm not sure why you set this, but doing so prevents `pre-commit` from running successfully when Python 3.11 isn't present. That's annoying when running `pre-commit` locally, so please remove it again.
created_at: 2025-03-25T07:15:04Z
author_association: OWNER
diff_hunk: @@ -5,23 +5,31 @@ on:
   - pull_request
 jobs:
   test:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     strategy:
       fail-fast: false
       matrix:
         python-version:
-          - 3.6
-          - 3.7
-          - 3.8
-          - 3.9
-          - pypy3
+          - "3.8"
+          - "3.9"
+          - "3.10"
+          - "3.11"
+          - "3.12"
+          # - "pypy3.9"
path: .github/workflows/main.yml
user: login: Dunedan
body: It'd be great to keep testing with PyPy. Could you please check if it works with PyPy 3.10?
```suggestion
          - "pypy3.10"
```
created_at: 2025-03-25T07:22:20Z
author_association: OWNER
diff_hunk: @@ -16,49 +18,53 @@ repos:
           - --allow-missing-credentials
       - id: detect-private-key
 
-  - repo: git://github.com/adrienverge/yamllint
-    rev: v1.25.0
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.35.1
     hooks:
       - id: yamllint
         args:
           - -s
 
-  - repo: git://github.com/PyCQA/isort
-    rev: 5.6.4
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.13.2
     hooks:
       - id: isort
         args:
           - --check-only
           - --diff
 
-  - repo: git://github.com/PyCQA/prospector/
-    rev: 1.3.1
-    hooks:
-      - id: prospector
-        additional_dependencies:
-          - django
-          - ipaddress
-          - prospector
+  # This hook fails with the following error
+  # `pylint: failure / Tool pylint failed to run (exception was raised)`
+  # It's an old version which needs more work to be brought up to date
+  # - repo: https://github.com/PyCQA/prospector/
+  #   rev: 1.3.1
+  #   hooks:
+  #     - id: prospector
+  #       additional_dependencies:
+  #         - django
+  #         - ipaddress
+  #         - prospector
+  #         - setuptools
path: .pre-commit-config.yaml
user: login: browniebroke
body: I was trying to avoid getting too many unrelated fixes in this PR, but I can add them if you don't mind. Or I can submit a PR to fix the CI before getting further on this? Let me know if you have a preference
created_at: 2025-03-25T09:23:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,7 +1,9 @@
 ---
+default_language_version:
+  python: python3.11
path: .pre-commit-config.yaml
user: login: browniebroke
body: That was an earlier attempt at fixing `prospector`. I had a strange error that seemed to indicate a breakage due a recent version of Python
created_at: 2025-03-25T09:23:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -5,23 +5,31 @@ on:
   - pull_request
 jobs:
   test:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     strategy:
       fail-fast: false
       matrix:
         python-version:
-          - 3.6
-          - 3.7
-          - 3.8
-          - 3.9
-          - pypy3
+          - "3.8"
+          - "3.9"
+          - "3.10"
+          - "3.11"
+          - "3.12"
+          # - "pypy3.9"
path: .github/workflows/main.yml
user: login: browniebroke
body: I'll take a look
created_at: 2025-03-25T09:24:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -16,49 +18,53 @@ repos:
           - --allow-missing-credentials
       - id: detect-private-key
 
-  - repo: git://github.com/adrienverge/yamllint
-    rev: v1.25.0
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.35.1
     hooks:
       - id: yamllint
         args:
           - -s
 
-  - repo: git://github.com/PyCQA/isort
-    rev: 5.6.4
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.13.2
     hooks:
       - id: isort
         args:
           - --check-only
           - --diff
 
-  - repo: git://github.com/PyCQA/prospector/
-    rev: 1.3.1
-    hooks:
-      - id: prospector
-        additional_dependencies:
-          - django
-          - ipaddress
-          - prospector
+  # This hook fails with the following error
+  # `pylint: failure / Tool pylint failed to run (exception was raised)`
+  # It's an old version which needs more work to be brought up to date
+  # - repo: https://github.com/PyCQA/prospector/
+  #   rev: 1.3.1
+  #   hooks:
+  #     - id: prospector
+  #       additional_dependencies:
+  #         - django
+  #         - ipaddress
+  #         - prospector
+  #         - setuptools
path: .pre-commit-config.yaml
user: login: browniebroke
body: I've extracted this in https://github.com/Dunedan/django-lockdown/pull/23 and hit a bit of blocker with prospector. I might try again later but I'm not familiar with the tool so any suggestions/pointers would be appreciated. Thanks
created_at: 2025-03-25T10:17:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -16,49 +18,53 @@ repos:
           - --allow-missing-credentials
       - id: detect-private-key
 
-  - repo: git://github.com/adrienverge/yamllint
-    rev: v1.25.0
+  - repo: https://github.com/adrienverge/yamllint
+    rev: v1.35.1
     hooks:
       - id: yamllint
         args:
           - -s
 
-  - repo: git://github.com/PyCQA/isort
-    rev: 5.6.4
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.13.2
     hooks:
       - id: isort
         args:
           - --check-only
           - --diff
 
-  - repo: git://github.com/PyCQA/prospector/
-    rev: 1.3.1
-    hooks:
-      - id: prospector
-        additional_dependencies:
-          - django
-          - ipaddress
-          - prospector
+  # This hook fails with the following error
+  # `pylint: failure / Tool pylint failed to run (exception was raised)`
+  # It's an old version which needs more work to be brought up to date
+  # - repo: https://github.com/PyCQA/prospector/
+  #   rev: 1.3.1
+  #   hooks:
+  #     - id: prospector
+  #       additional_dependencies:
+  #         - django
+  #         - ipaddress
+  #         - prospector
+  #         - setuptools
path: .pre-commit-config.yaml
user: login: Dunedan
body: > I was trying to avoid getting too many unrelated fixes in this PR, but I can add them if you don't mind. Or I can submit a PR to fix the CI before getting further on this? Let me know if you have a preference

I'm fine with both approaches, but splitting different topics into different PRs is probably the easier way. :+1:
created_at: 2025-03-25T14:10:41Z
author_association: OWNER

PR comments:
user: login: browniebroke
created_at: 2025-03-22T15:24:30Z
body: It took a while to get this into a green state ready to merge, but I think it's now good. Since that was open, Django 5.1 and Python 3.13 were released, Python 3.8 went EOL and Django 5.2 is just around the corner.

I'm happy to update (add + remove) support accordingly but I'd rather do it in a follow up pull request, and it might be best to make a release before we do so.
author_association: CONTRIBUTOR
user: login: browniebroke
created_at: 2025-03-22T20:41:26Z
body: @Dunedan are you still interested in keeping this project going? I just noticed that the last commit to main is 4 years old... While the project is probably "done" and doesn't need much attention, Django keeps evolving.

If you no longer use Django (life moves on), you may consider a move to @django-commons
author_association: CONTRIBUTOR
user: login: browniebroke
created_at: 2025-03-27T16:30:35Z
body: I've also added Python 3.13 and Django 5.1, as it all passed.
author_association: CONTRIBUTOR
user: login: Dunedan
created_at: 2025-03-28T09:11:19Z
body: Thanks a lot for your contributions. Very much appreciated. This looks good to me and I'm going to merge it as well.

I'll wait a week or so until Django 5.2 gets released to add formal support for it too, before releasing a new version of `django-lockdown`, which will then be available via PyPI.
author_association: OWNER