# HG changeset patch # User Hugo Rodger-Brown # Date 1697812487 -3600 # Fri Oct 20 15:34:47 2023 +0100 # Node ID 5504b7be90272631887001cff397fbfd6fcbdf39 # Parent c0672089c42607eda5f423483cdc79092c9d1efa Add Django 5.0 compatibility (reverse function) I have added a `compat` module to handle the migration of the `reverse` function from django.core.urlresolvers to django.urls. I have updated the tests to handle the change in 4.2 to 5.0 where request params passed to a SimpleListFilter are passed as list of values, not just one. I have updated the build matrix to include Django5.0 and the main branch, as well as Python 3.12. diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -6,10 +6,12 @@ **.pyc MANIFEST .idea +.venv +*.egg-info syntax:regexp ^htmlcov$ ^env$ syntax: glob *.komodoproject -.DS_Store \ No newline at end of file +.DS_Store diff --git a/MANIFEST.in b/MANIFEST.in --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include BSD-LICENSE include CHANGELOG +include LICENSE include README.rst recursive-include impersonate/templates * diff --git a/impersonate/admin.py b/impersonate/admin.py --- a/impersonate/admin.py +++ b/impersonate/admin.py @@ -5,15 +5,11 @@ from django.db.utils import NotSupportedError from django.utils.html import format_html +from .compat import reverse from .helpers import User, check_allow_impersonate from .models import ImpersonationLog from .settings import settings -try: - from django.urls import reverse -except ImportError: - from django.core.urlresolvers import reverse - logger = logging.getLogger(__name__) diff --git a/impersonate/compat.py b/impersonate/compat.py new file mode 100644 --- /dev/null +++ b/impersonate/compat.py @@ -0,0 +1,7 @@ +# compatibility module for handling Django upgrade namespace changes +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse + +__all__ = ["reverse"] diff --git a/impersonate/middleware.py b/impersonate/middleware.py --- a/impersonate/middleware.py +++ b/impersonate/middleware.py @@ -2,10 +2,11 @@ from datetime import datetime, timedelta, timezone from django.http import HttpResponseNotAllowed -from django.shortcuts import redirect, reverse +from django.shortcuts import redirect from django.utils.deprecation import MiddlewareMixin from django.utils.functional import SimpleLazyObject +from .compat import reverse from .helpers import User, check_allow_for_uri, check_allow_for_user, check_read_only from .settings import settings diff --git a/impersonate/tests.py b/impersonate/tests.py --- a/impersonate/tests.py +++ b/impersonate/tests.py @@ -35,17 +35,15 @@ from django.utils.duration import duration_string from .admin import ( - ImpersonationLogAdmin, ImpersonatorFilter, SessionStateFilter, + ImpersonationLogAdmin, + ImpersonatorFilter, + SessionStateFilter, ) +from .compat import reverse from .helpers import users_impersonable from .models import ImpersonationLog from .signals import session_begin, session_end -try: - from django.urls import reverse -except ImportError: - from django.core.urlresolvers import reverse - User = get_user_model() django_version_loose = LooseVersion(django.get_version()) @@ -725,9 +723,16 @@ qs = _filter.queryset(None, ImpersonationLog.objects.all()) self.assertEqual(qs.count(), 2) + def _format_params(val): + # Django 5.x returns request querystring params as a list + # https://github.com/django/django/commit/d03dc63177ad3ba6e685e314eed45d6a8ec5cb0c + if django_version_loose >= '5.0': + return {'session': [val]} + return {'session': val} + _filter = SessionStateFilter( None, - {'session': 'complete'}, + _format_params('complete'), ImpersonationLog, ImpersonationLogAdmin, ) @@ -736,7 +741,7 @@ _filter = SessionStateFilter( None, - {'session': 'incomplete'}, + _format_params('incomplete'), ImpersonationLog, ImpersonationLogAdmin, ) diff --git a/impersonate/views.py b/impersonate/views.py --- a/impersonate/views.py +++ b/impersonate/views.py @@ -8,8 +8,12 @@ from .decorators import allowed_user_required from .helpers import ( - check_allow_for_user, get_paginator, get_redir_arg, get_redir_field, - get_redir_path, users_impersonable, + check_allow_for_user, + get_paginator, + get_redir_arg, + get_redir_field, + get_redir_path, + users_impersonable, ) from .settings import User, settings from .signals import session_begin, session_end diff --git a/pyproject.toml b/pyproject.toml --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.black] line-length = 79 skip-string-normalization = true -target-version = ['py37', 'py38'] +target-version = ['py37', 'py38', 'py39', 'py310', 'py311', 'py312'] include = '\.pyi?$' exclude = ''' diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -48,11 +48,16 @@ 'Framework :: Django :: 2.2', 'Framework :: Django :: 3.2', 'Framework :: Django :: 4.0', + 'Framework :: Django :: 4.1', + 'Framework :: Django :: 4.2', + 'Framework :: Django :: 5.0', 'Programming Language :: Python', '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', 'Environment :: Web Environment', ], ) diff --git a/tox.ini b/tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,28 @@ [tox] downloadcache = {toxworkdir}/cache/ -envlist = py{37,38,39}-django{2.2,3.2},py{38,39}-django{4.0},py310-django{3.2,4.0} +; https://docs.djangoproject.com/en/2.2/faq/install/ +; https://docs.djangoproject.com/en/5.0/faq/install/ +envlist = + py{37,38,39}-django2.2 + ; Django 3.0 / 3.1 not included in PyPI classifiers + ; py{37,38,39}-django3.0 + ; py{37,38,39}-django3.1 + py{37,38,39,310}-django3.2 + py{38,39,310}-django4.0 + py{38,39,310}-django4.1 + py{38,39,310,311}-django4.1 + py{38,39,310,311}-django4.2 + py{310,311,312}-django{5.0,main} [testenv] commands = {envpython} runtests.py deps = django2.2: django>=2.2,<3.0 - django3.2: django>=3.2,<4.0 + django3.0: django>=3.0,<3.1 + django3.1: django>=3.1,<3.2 + django3.2: django>=3.2,<3.3 django4.0: django>=4.0,<4.1 + django4.1: django>=4.1,<4.2 + django4.2: django>=4.2,<4.3 + django5.0: https://github.com/django/django/archive/stable/5.0.x.tar.gz + djangomain: https://github.com/django/django/archive/main.tar.gz