# HG changeset patch
# User Hugo Rodger-Brown
# Date 1681222628 -3600
# Tue Apr 11 15:17:08 2023 +0100
# Node ID 4abfc208f5ac1289c52f7d2b2ace9abddd1bb46c
# Parent 76e93d43501e5304d6b27e7f7072e4d8aab15104
Add support for Django 5.0 (pre)
Adds a compat module that handles the deprecation of timezone.utc
in upcoming versions of Python.
Updates the classifiers to include latest versions of Python and
Django.
Updates the tox configuration to make the python/django support
clearer.
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,15 +1,16 @@
syntax:glob
+.*.swp
.coverage
+.DS_Store
+.idea
.tox
-settings_local.py
-.*.swp
+.venv
+*.diff
+*.komodoproject
**.pyc
MANIFEST
-.idea
+settings_local.py
syntax:regexp
^htmlcov$
^env$
-syntax: glob
-*.komodoproject
-.DS_Store
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,4 @@
-include BSD-LICENSE
+include LICENSE
include CHANGELOG
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,12 @@
+try:
+ from django.urls import reverse
+except ImportError:
+ from django.core.urlresolvers import reverse
+
+
+# timezone.utc removed in Django 5
+try:
+ from django.utils.timezone import utc
+except ImportError:
+ from zoneinfo import ZoneInfo
+ utc = ZoneInfo("UTC")
diff --git a/impersonate/middleware.py b/impersonate/middleware.py
--- a/impersonate/middleware.py
+++ b/impersonate/middleware.py
@@ -2,11 +2,11 @@
from datetime import datetime, timedelta
from django.http import HttpResponseNotAllowed
-from django.shortcuts import redirect, reverse
-from django.utils import timezone
+from django.shortcuts import redirect
from django.utils.deprecation import MiddlewareMixin
from django.utils.functional import SimpleLazyObject
+from .compat import reverse, timezone
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
@@ -19,7 +19,7 @@
is_superuser = False
is_staff = False
'''
-from datetime import datetime, timedelta, timezone
+from datetime import datetime, timedelta
from distutils.version import LooseVersion
from unittest.mock import PropertyMock, patch
from urllib.parse import urlencode, urlsplit
@@ -35,17 +35,15 @@
from django.utils.duration import duration_string
from .admin import (
- ImpersonationLogAdmin, ImpersonatorFilter, SessionStateFilter,
+ ImpersonationLogAdmin,
+ ImpersonatorFilter,
+ SessionStateFilter,
)
+from .compat import reverse, timezone
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,17 @@
qs = _filter.queryset(None, ImpersonationLog.objects.all())
self.assertEqual(qs.count(), 2)
+ # from 5.0 admin list filter values are multi-valued
+ if django_version_loose < "5.0":
+ params_complete = {'session': 'complete'}
+ params_incomplete = {'session': 'complete'}
+ else:
+ params_complete = {'session': ['complete']}
+ params_incomplete = {'session': ['incomplete']}
+
_filter = SessionStateFilter(
None,
- {'session': 'complete'},
+ params_complete,
ImpersonationLog,
ImpersonationLogAdmin,
)
@@ -736,7 +742,7 @@
_filter = SessionStateFilter(
None,
- {'session': 'incomplete'},
+ params_incomplete,
ImpersonationLog,
ImpersonationLogAdmin,
)
diff --git a/impersonate/views.py b/impersonate/views.py
--- a/impersonate/views.py
+++ b/impersonate/views.py
@@ -5,12 +5,16 @@
from django.db.models import Q
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, render
-from django.utils import timezone
+from .compat import timezone
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']
include = '\.pyi?$'
exclude = '''
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -48,11 +48,14 @@
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.2',
'Framework :: Django :: 4.0',
+ 'Framework :: Django :: 4.1',
+ 'Framework :: Django :: 4.2',
'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',
'Environment :: Web Environment',
],
)
diff --git a/tox.ini b/tox.ini
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,20 @@
[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}
+envlist =
+ py37-django{22,30,31,32}
+ py38-django{22,30,31,32,40,41}
+ py39-django{22,30,31,32,40,41}
+ py310-django{32,40,41,42,main}
+ py311-django{41,42,main}
[testenv]
commands = {envpython} runtests.py
deps =
- django2.2: django>=2.2,<3.0
- django3.2: django>=3.2,<4.0
- django4.0: django>=4.0,<4.1
+ django22: django>=2.2,<3.0
+ django30: django>=3.0,<3.1
+ django31: django>=3.1,<3.2
+ django32: django>=3.2,<4.0
+ django40: django>=4.0,<4.1
+ django41: django>=4.1,<4.2
+ django42: django>=4.2,<4.3
+ djangomain: https://github.com/django/django/archive/main.tar.gz