Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id B35CA81537 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Tue, 25 Apr 2023 10:55:53 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.128.45; helo=mail-wm1-f45.google.com; envelope-from=hugo@yunojuno.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (2048-bit key; unprotected) header.d=yunojuno-com.20221208.gappssmtp.com header.i=@yunojuno-com.20221208.gappssmtp.com header.b=Dnz7bH8d Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mail.netlandish.com (Postfix) with ESMTP id 2024D152FC8 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Tue, 25 Apr 2023 10:55:51 +0000 (UTC) Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-3f1957e80a2so109590055e9.1 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Tue, 25 Apr 2023 03:55:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yunojuno-com.20221208.gappssmtp.com; s=20221208; t=1682420150; x=1685012150; h=to:from:date:user-agent:message-id:subject :content-transfer-encoding:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=CDbUKrCQi6Zd445OqQr1yVNzp914OJMPGi1e6b9JxXo=; b=Dnz7bH8dFkS8AwGypa9vxN8lRDo6pDsq2z/j86CPRxl8C2S2q9IxGoPXNYQbHduo87 2wTjeD2YEYAeh8kivca3MNPx2pyOQFfxJPdXS+fG9X+ZfglMgfOh1busLGk66+9AQYe/ fjL/hHld3d7wdDDjx7AtPZX33Xqm4jmIXL9w0a+dA0lQMsUpOh3bxR3XzmllyARmYrjL 9OrR09pTN9ScPglBZUkv+IQKLGwrotzhG2r2nghc64jHqbYBqKzUUAhg8WN9z1UnCFcu /5gfmG/mu6JfXfIAHxXBfU1ZiFF32pzT6ZQKg2py77+xuaKYL1IDX+5jNrpMan2y0NGE nTBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682420150; x=1685012150; h=to:from:date:user-agent:message-id:subject :content-transfer-encoding:mime-version:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=CDbUKrCQi6Zd445OqQr1yVNzp914OJMPGi1e6b9JxXo=; b=S+44eAP0oQ9pViWQczNUq/6D8rSFplow4c2LeUdOWAPWT21vN6mBhgj1ZQhavIfjnV fUVPXhxMndnNz8UorEeruoN7OpCpSnZ9eMQm+0iaZV82Xtj9LSLN5DOsKhehP7yoJ9m6 T7nQUBFFG3SluNA+IPZrnzpPPD4+INohtjtjx3UYs7J+sK/h4KJO3QBtQyAwhAwJPHtM sbjr0Jln4MtPVpG2qk2/NyynYvUoTAYqto2ZRuijFb6K14l9r/xtG2ohSsmqqJf1t9uy 9OWxGmnUoRjo9Zs9tBmVCaRFyk8qsq1uMgjIGJGN4LwbTjmB0ZBtsb4HrC1o3nxqox3Q 7vqQ== X-Gm-Message-State: AAQBX9ev11aVGTML4mJs4C58tmJbUR9ddo0/5jfPG/RY8rcJpHIY5EIp A30Y3ISaTg/0UyUlYYiITFtQZNTsjgGsQB4ZfM5jQA== X-Google-Smtp-Source: AKy350ZnOWZf/QlbL9Ji+NH4ufhri1ZEWUsGjuKcCOuFMgqgI3Ac6hMroYFy2qTKLec6ufHspJgk3Q== X-Received: by 2002:adf:cd8e:0:b0:2ef:afe0:727a with SMTP id q14-20020adfcd8e000000b002efafe0727amr12969026wrj.12.1682420149798; Tue, 25 Apr 2023 03:55:49 -0700 (PDT) Received: from [127.0.0.1] ([104.28.231.254]) by smtp.gmail.com with ESMTPSA id e18-20020adffc52000000b002efacde3fc7sm12780355wrs.35.2023.04.25.03.55.49 for <~petersanchez/public-inbox@lists.code.netlandish.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Apr 2023 03:55:49 -0700 (PDT) MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Subject: [PATCH django-impersonate] Add support for Django 5.0 (pre) X-Mercurial-Node: bb4fbfb81186e418ce55d199d60765d473cfe3d5 X-Mercurial-Series-Index: 1 X-Mercurial-Series-Total: 1 Message-Id: X-Mercurial-Series-Id: User-Agent: Mercurial-patchbomb/6.4rc0 Date: Tue, 25 Apr 2023 11:55:48 +0100 From: =?iso-8859-1?q?Hugo_Rodger-Brown?= To: ~petersanchez/public-inbox@lists.code.netlandish.com # HG changeset patch # User Hugo Rodger-Brown # Date 1681222628 -3600 # Tue Apr 11 15:17:08 2023 +0100 # Node ID bb4fbfb81186e418ce55d199d60765d473cfe3d5 # 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/__init__.py b/impersonate/compat/__init__.py new file mode 100644 --- /dev/null +++ b/impersonate/compat/__init__.py @@ -0,0 +1,4 @@ +from .timezone import utc +from .urls import reverse + +__all__ = ['reverse', 'utc'] diff --git a/impersonate/compat/timezone.py b/impersonate/compat/timezone.py new file mode 100644 --- /dev/null +++ b/impersonate/compat/timezone.py @@ -0,0 +1,6 @@ +# 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/compat/urls.py b/impersonate/compat/urls.py new file mode 100644 --- /dev/null +++ b/impersonate/compat/urls.py @@ -0,0 +1,4 @@ +try: + from django.urls import reverse +except ImportError: + from django.core.urlresolvers import reverse 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