Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id 4CD6581385 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Fri, 20 Oct 2023 15:31:38 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.218.49; helo=mail-ej1-f49.google.com; envelope-from=hugo@yunojuno.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (2048-bit key; unprotected) header.d=yunojuno-com.20230601.gappssmtp.com header.i=@yunojuno-com.20230601.gappssmtp.com header.b=cDcZx51R Received: from mail-ej1-f49.google.com (mail-ej1-f49.google.com [209.85.218.49]) by mail.netlandish.com (Postfix) with ESMTP id 83380152FB1 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Fri, 20 Oct 2023 15:31:36 +0000 (UTC) Received: by mail-ej1-f49.google.com with SMTP id a640c23a62f3a-99bdeae1d0aso150865366b.1 for <~petersanchez/public-inbox@lists.code.netlandish.com>; Fri, 20 Oct 2023 08:31:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yunojuno-com.20230601.gappssmtp.com; s=20230601; t=1697815895; x=1698420695; darn=lists.code.netlandish.com; h=to:from:date:user-agent:references:in-reply-to:message-id:subject :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=xW/dPDmikHvzAJKqwzXk52W5yotdkcQQoUqn4p22tuA=; b=cDcZx51RFrHUTYXXpCUCMDQGnxB5SRd43wBeO8umYiN9PUU4Iype5/SugIbqRxJgzw RnfMFsPiqvK0e0pqgo4LpT3iyH7pGbxPVUEMpzdm/PZFfYuyErHaCcQxTX9bshgkE70D 3xgUJT6Mg8bqfdTYTImjcstUvgVWfe2cRObk32qmhzvu9XFSPMpS3IYX0cBjOT9N7z/h QW5I40VJdBI0xzX45BreMRWfh7yVWixJ3jEkHDaTOECh7gTY/aXrPIxxFvcAqIFQ+SY8 9078wWvm4ibSZUQyGPXUp/bbi3mFyr3p2MvRYuD6Q9AK64LJtJFUrHy2xob+OM6KGeDs lr5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1697815895; x=1698420695; h=to:from:date:user-agent:references:in-reply-to:message-id:subject :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=xW/dPDmikHvzAJKqwzXk52W5yotdkcQQoUqn4p22tuA=; b=j+Zondk4OD7tT0+W06OR747ZqN0+QGPK+swVPntGTByyKHjaYLTF7Sj73Co2GvWlna 8bAW0R9kDPW3vV6ieW+S658v0QSYky06ZRXfHJiIjrRwiG806mfzFNx4x1yOaiQ3Rfyz IBdXy4We9TdUGikfvtct9kaIXz3PNpo+cgYBTcHCQaF2ePmKaCv0s8Ti2W+0OsNgRm64 RNiC8leWcXZRhEz1DB5vM855mMiZK4ZDMGVQj6hZ5lLHgWeCE2XL+7NEwpmKCVChNBSV cB7KRlxwaN+3NqUrpEEPTCvBC1wbHprq0QXV40/UtLf+YYcV1fGPm399mSWwpsnMg2ZY DZzg== X-Gm-Message-State: AOJu0Yy2GwvQgSJitH5MR7/UHMY0vQUI8oKNd36MpIyNeJ8xvpLKMCGR GlGmEg9rpyTjci9CoPJGz4cixEb4DCBK7H979GZTiio/kcpzQEkf9jrBuPQRMvMsGumPEaY18z/ us7fOuYTNVV9BY28jq+ZIpDvNeccfk1zUtIYxVMKC6bWyEoHXtxXQAW7G4r0HMw== X-Google-Smtp-Source: AGHT+IFHss5WULZ5wfn1Q97jLqx+9NXsIF18EkCJ96JaJ6wMaHGRLAiir367y7uR0xwGTINP7U0o0g== X-Received: by 2002:a17:907:7da7:b0:9a9:ef41:e5c7 with SMTP id oz39-20020a1709077da700b009a9ef41e5c7mr1668057ejc.8.1697815894843; Fri, 20 Oct 2023 08:31:34 -0700 (PDT) Received: from h12h5hdzq6x8.lan ([5.80.29.162]) by smtp.gmail.com with ESMTPSA id dv24-20020a170906b81800b009a168ab6ee2sm1671730ejb.164.2023.10.20.08.31.33 for <~petersanchez/public-inbox@lists.code.netlandish.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 20 Oct 2023 08:31:33 -0700 (PDT) MIME-Version: 1.0 Subject: [PATCH 1 of 1 django-impersonate] Add Django 5.0 compatibility (reverse function) X-Mercurial-Node: d20f3e8b605d1ca56d3f527ed85c1e366213c276 X-Mercurial-Series-Index: 1 X-Mercurial-Series-Total: 1 Message-Id: X-Mercurial-Series-Id: In-Reply-To: References: User-Agent: Mercurial-patchbomb/6.5.1 Date: Fri, 20 Oct 2023 16:31:33 +0100 From: =?iso-8859-1?q?Hugo_Rodger-Brown?= To: ~petersanchez/public-inbox@lists.code.netlandish.com Content-Type: text/plain; charset="US-ASCII" # HG changeset patch # User Hugo Rodger-Brown # Date 1697812487 -3600 # Fri Oct 20 15:34:47 2023 +0100 # Node ID d20f3e8b605d1ca56d3f527ed85c1e366213c276 # 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 -- Disclaimer: This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. This message contains confidential information and is intended only for the individual named. If you are not the named addressee, you should not disseminate, distribute or copy this email. Please notify the sender immediately by email if you have received this email by mistake and delete this email from your system. If you are not the intended recipient, you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited. YunoJuno is 100% compliant with the GDPR data protection regulation. Visit our privacy policy to learn how we collect, keep, and process your private information in accordance with these laws at www.yunojuno.com .