<CAA3-rkY1uAmcQtvtBUG3qyVsQM4YbSPXo4B8w0CxKRu3m8i2Ng@mail.gmail.com># 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
<20230424230021.ntp626fnwo5d6jri@thinkpad>
<CAA3-rkY1uAmcQtvtBUG3qyVsQM4YbSPXo4B8w0CxKRu3m8i2Ng@mail.gmail.com>
(view parent)
Thank you for this patch but it doesn't apply cleanly. Seems like most
changes fail to apply. Did you make sure you have the latest version
pulled into your clone?
Thanks,
Peter
On 03/08, Hugo Rodger-Brown wrote:
# 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