# HG changeset patch
# User Hugo Rodger-Brown <hugo@yunojuno.com>
# Date 1678268809 0
# Wed Mar 08 09:46:49 2023 +0000
# Node ID c0c223b5e10524c9cad20de0b11d901277f5b89d
# Parent 76e93d43501e5304d6b27e7f7072e4d8aab15104
Add compat module to handle removal of timzone.utc
In Django 5 the way in which timezones are handled is updated, and a side-effect
of this is that the `utc` value is removed from `django.utils.timezone`. I have
created a new `compat.py` module to handle both scenarios and expose a value
called `UTC` that can be used wherever a tzinfo is required.
At the same time I have moved the `reverse` import code into the same module so
it it centralised.
I have also updated the build matrix to include Python 3.10, 3.11, and Django
4.1, "main".
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,15 @@
+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
+ UTC = utc
+except ImportError:
+ from zoneinfo import ZoneInfo
+ UTC = ZoneInfo("UTC")
+
+
+__all__ = ["reverse", "UTC"]
diff --git a/impersonate/middleware.py b/impersonate/middleware.py
--- a/impersonate/middleware.py
+++ b/impersonate/middleware.py
@@ -3,10 +3,10 @@
from django.http import HttpResponseNotAllowed
from django.shortcuts import redirect, reverse
-from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin
from django.utils.functional import SimpleLazyObject
+from .compat import UTC
from .helpers import User, check_allow_for_uri, check_allow_for_user,
check_read_only
from .settings import settings
@@ -33,11 +33,11 @@
return
start_time = datetime.fromtimestamp(
- request.session['_impersonate_start'], timezone.utc
+ request.session['_impersonate_start'], UTC
)
delta = timedelta(seconds=settings.MAX_DURATION)
- if datetime.now(timezone.utc) - start_time > delta:
+ if datetime.now(UTC) - start_time > delta:
return redirect('impersonate-stop')
new_user_id = request.session['_impersonate']
diff --git a/impersonate/tests.py b/impersonate/tests.py
--- a/impersonate/tests.py
+++ b/impersonate/tests.py
@@ -40,11 +40,7 @@
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
+from .compat import reverse, UTC
User = get_user_model()
django_version_loose = LooseVersion(django.get_version())
@@ -154,7 +150,7 @@
@override_settings(IMPERSONATE={'MAX_DURATION': 3600})
def test_impersonated_request_with_max_duration(self):
self._impersonated_request(
- _impersonate_start=datetime.now(timezone.utc).timestamp()
+ _impersonate_start=datetime.now(UTC).timestamp()
)
@override_settings(IMPERSONATE={'MAX_DURATION': 5, 'REDIRECT_URL': '/foo/'})
@@ -163,12 +159,12 @@
See Issue #67
'''
self._impersonated_request(
- _impersonate_start=datetime.now(timezone.utc).timestamp()
+ _impersonate_start=datetime.now(UTC).timestamp()
)
# new request to see if the redirect to stop
request = self.factory.get('/')
request.user = self.superuser
- past_time = datetime.now(timezone.utc) - timedelta(hours=1)
+ past_time = datetime.now(UTC) - timedelta(hours=1)
request.session = {
'_impersonate': self.user,
'_impersonate_start': past_time.timestamp(),
@@ -207,7 +203,7 @@
request.session = {
'_impersonate': self.user.pk,
'_impersonate_start': (
- datetime.now(timezone.utc) - timedelta(seconds=3601)
+ datetime.now(UTC) - timedelta(seconds=3601)
).timestamp(),
}
response = self.middleware.process_request(request)
diff --git a/impersonate/views.py b/impersonate/views.py
--- a/impersonate/views.py
+++ b/impersonate/views.py
@@ -5,7 +5,6 @@
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 .decorators import allowed_user_required
from .helpers import (
@@ -14,6 +13,7 @@
)
from .settings import User, settings
from .signals import session_begin, session_end
+from .compat import UTC
logger = logging.getLogger(__name__)
@@ -39,7 +39,7 @@
if check_allow_for_user(request, new_user):
request.session['_impersonate'] = new_user.pk
request.session['_impersonate_start'] = datetime.now(
- tz=timezone.utc
+ tz=UTC
).timestamp()
prev_path = request.META.get('HTTP_REFERER')
if prev_path:
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,13 @@
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.2',
'Framework :: Django :: 4.0',
+ 'Framework :: Django :: 4.1',
'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,6 +1,6 @@
[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 = py{37,38,39}-django{2.2,3.2},py{38,39}-django{4.0,4.1},py310-django{3.2,4.0,4.1},py311-django{3.2,4.0,4.1,main}
[testenv]
commands = {envpython} runtests.py
@@ -8,3 +8,5 @@
django2.2: django>=2.2,<3.0
django3.2: django>=3.2,<4.0
django4.0: django>=4.0,<4.1
+ django4.1: django>=4.1,<4.2
+ djangomain: https://github.com/django/django/archive/main.tar.gz