From 3e207fa43e8a64ab7c7dfd4d245ae156932b1cfa Mon Sep 17 00:00:00 2001 From: cactusman Date: Wed, 20 Sep 2023 16:09:03 +0900 Subject: [PATCH] =?UTF-8?q?Django=204.2=E5=AF=BE=E5=BF=9C=20(#23)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Django 4.2対応 --- .github/workflows/ci.yml | 16 +++++++++------- ChangeLog.rst | 9 +++++++++ docs/en/source/forms.rst | 2 +- newauth/__init__.py | 2 +- newauth/admin.py | 2 +- newauth/decorators.py | 4 ++-- newauth/models.py | 2 +- newauth/signals.py | 4 ++-- newauth/test.py | 9 +++++++-- newauth/views.py | 7 ++----- setup.py | 8 ++++---- tests/test_api.py | 14 +++++++++----- tests/test_middleware.py | 9 +++++++-- tests/test_views.py | 16 +++++++++++++--- tox.ini | 12 ++++++------ 15 files changed, 74 insertions(+), 42 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03e848b..67abe1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,19 +10,21 @@ jobs: fail-fast: false max-parallel: 5 matrix: - python-version: ['3.6', '3.7', '3.8', '3.9', '3.10'] - django-version: ['2.2', '3.2'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12-dev'] + django-version: ['3.2', '4.1', '4.2'] include: - - django-version: 'main' - python-version: '3.9' - django-version: 'main' python-version: '3.10' + - django-version: 'main' + python-version: '3.11' + - django-version: 'main' + python-version: '3.12-dev' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -32,7 +34,7 @@ jobs: echo "::set-output name=dir::$(pip cache dir)" - name: Cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.pip-cache.outputs.dir }} key: diff --git a/ChangeLog.rst b/ChangeLog.rst index 3c9794e..343588b 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -2,9 +2,18 @@ ChangeLog ========= +Release 0.43 (Unreleased) +========================= + + Release 0.42 (Unreleased) ========================= +- Support Django-4.2 +- Support Python-3.11, 3.12 +- Drop Django-2.2 +- Drop Python-3.6, 3.7 + Release 0.41 (2022-08-16) ========================= diff --git a/docs/en/source/forms.rst b/docs/en/source/forms.rst index 253e9cc..3e83b5c 100644 --- a/docs/en/source/forms.rst +++ b/docs/en/source/forms.rst @@ -13,7 +13,7 @@ message. .. code-block:: python from django import forms - from django.utils.translation import ugettext_lazy as _ + from django.utils.translation import gettext_lazy as _ from newauth.forms import BaseAuthForm class AuthForm(BaseAuthForm): diff --git a/newauth/__init__.py b/newauth/__init__.py index c0768b6..80a7f56 100644 --- a/newauth/__init__.py +++ b/newauth/__init__.py @@ -1,2 +1,2 @@ -VERSION_INFO = (0, 41) +VERSION_INFO = (0, 42) VERSION = '.'.join(map(str, VERSION_INFO)) diff --git a/newauth/admin.py b/newauth/admin.py index 201cea8..7a2f69d 100644 --- a/newauth/admin.py +++ b/newauth/admin.py @@ -12,7 +12,7 @@ from django.contrib.admin.helpers import AdminForm from django.contrib.admin.utils import flatten_fieldsets from django.forms.models import modelform_factory -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters from django.shortcuts import render, get_object_or_404 diff --git a/newauth/decorators.py b/newauth/decorators.py index 4f3040d..dcaa0e2 100644 --- a/newauth/decorators.py +++ b/newauth/decorators.py @@ -1,9 +1,9 @@ #:coding=utf-8: from functools import wraps +from urllib.parse import quote from django.http import HttpResponseRedirect -from django.utils.http import urlquote from newauth.constants import REDIRECT_FIELD_NAME from newauth.api import get_backends, get_user_from_request @@ -23,7 +23,7 @@ def decorator(view_func): def _wrapped_view(request, *args, **kwargs): if test_func(get_user_from_request(request)): return view_func(request, *args, **kwargs) - path = urlquote(request.get_full_path()) + path = quote(request.get_full_path()) tup = login_url, redirect_field_name, path return HttpResponseRedirect('%s?%s=%s' % tup) return _wrapped_view diff --git a/newauth/models.py b/newauth/models.py index c74eeba..7cd87b6 100644 --- a/newauth/models.py +++ b/newauth/models.py @@ -25,7 +25,7 @@ def _get_user_models(model_name=None): model_path = backend_data[model_name]['user'] anon_model_path = backend_data[model_name]['anon_user'] except IndexError: - if model_name is 'default': + if model_name == 'default': raise ImproperlyConfigured('A "default" user model is not specified. You must specify a "default" user model. Or maybe NEWAUTH_USER_MODELS isn\'t a correctly defined dict?') else: raise ImproperlyConfigured('Error importing User model class with name "%s". Is NEWAUTH_USER_MODELS a correctly defined dict?' % model_name) diff --git a/newauth/signals.py b/newauth/signals.py index b985b86..a82ea02 100644 --- a/newauth/signals.py +++ b/newauth/signals.py @@ -3,7 +3,7 @@ from django.dispatch import Signal -user_logged_in = Signal(providing_args=['request', 'user']) +user_logged_in = Signal() """ This is `django.dispatch.Signal` instances. This is sent at the end of the `newauth.api.login()` method. @@ -24,7 +24,7 @@ """ -user_logged_out = Signal(providing_args=['request', 'user']) +user_logged_out = Signal() """ This is `django.dispatch.Signal` instances. This is sent at the end of the `newauth.api.logout()` method. diff --git a/newauth/test.py b/newauth/test.py index d56025b..4db6498 100644 --- a/newauth/test.py +++ b/newauth/test.py @@ -1,4 +1,9 @@ from importlib import import_module +from django.http import HttpResponse + + +def get_response_empty(request): + return HttpResponse() class AuthTestCaseMixin(object): @@ -30,8 +35,8 @@ def auth_login(self, **credentials): # Create a fake request to store login details. request = HttpRequest() - SessionMiddleware().process_request(request) - AuthMiddleware().process_request(request) + SessionMiddleware(get_response_empty).process_request(request) + AuthMiddleware(get_response_empty).process_request(request) if self.client.session: request.session = self.client.session else: diff --git a/newauth/views.py b/newauth/views.py index d16d2fd..0e6b3ba 100644 --- a/newauth/views.py +++ b/newauth/views.py @@ -8,17 +8,14 @@ from django.views.decorators.cache import never_cache from django.views.decorators.debug import sensitive_post_parameters from django.conf import settings -from django.utils.http import is_safe_url +from django.utils.http import url_has_allowed_host_and_scheme from newauth.api import login as auth_login, logout as auth_logout from newauth.forms import BasicAuthForm def _is_safe_url(redirect_to, request): - if django.VERSION < (1, 11): - return is_safe_url(redirect_to, host=request.get_host()) - else: - return is_safe_url(redirect_to, allowed_hosts={request.get_host()}) + return url_has_allowed_host_and_scheme(redirect_to, allowed_hosts={request.get_host()}) @sensitive_post_parameters() diff --git a/setup.py b/setup.py index 3feb298..d3d044a 100644 --- a/setup.py +++ b/setup.py @@ -23,23 +23,23 @@ def read(filename): 'Development Status :: 3 - Alpha', 'Environment :: Plugins', 'Framework :: Django', - 'Framework :: Django :: 2.2', 'Framework :: Django :: 3.2', + 'Framework :: Django :: 4.2', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - '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', 'Topic :: Software Development :: Libraries :: Python Modules', ], include_package_data=True, packages=find_packages(), install_requires=[ - 'Django>=2.2', + 'Django>=3.2', ], test_suite='tests.main', zip_safe=False, diff --git a/tests/test_api.py b/tests/test_api.py index 06f221f..9f26082 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,6 +1,6 @@ #:coding=utf-8: -from django.http import HttpRequest +from django.http import HttpRequest, HttpResponse from django.test import TestCase as DjangoTestCase from django.conf import settings from django.contrib.sessions.middleware import SessionMiddleware @@ -13,6 +13,10 @@ from newauth.signals import user_logged_in, user_logged_out +def get_response_empty(request): + return HttpResponse() + + @pytest.mark.django_db class AuthTestCase(DjangoTestCase): fixtures = ['authutils_testdata.json'] @@ -127,8 +131,8 @@ def test_logout_when_logged_in(self, user_logged_out_send, user_logged_in_send): user = authenticate(user_id=1, _backend_name='testapp3') self.assertTrue(user.is_authenticated(), "%s is not authenticated" % user) - SessionMiddleware().process_request(request) - AuthMiddleware().process_request(request) + SessionMiddleware(get_response_empty).process_request(request) + AuthMiddleware(get_response_empty).process_request(request) self.assertTrue(hasattr(request, 'auth_user'), 'Request has no auth_user attribute') self.assertTrue(request.auth_user.is_anonymous(), 'User "%s" is authenticated' % request.auth_user) @@ -178,8 +182,8 @@ def test_logout_when_logged_out(self, user_logged_out_send): """ request = HttpRequest() - SessionMiddleware().process_request(request) - AuthMiddleware().process_request(request) + SessionMiddleware(get_response_empty).process_request(request) + AuthMiddleware(get_response_empty).process_request(request) self.assertTrue(hasattr(request, 'auth_user'), 'Request has no auth_user attribute') self.assertTrue(request.auth_user.is_anonymous(), 'User "%s" is authenticated' % request.auth_user) diff --git a/tests/test_middleware.py b/tests/test_middleware.py index fad0f6e..7116d1d 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -3,19 +3,24 @@ import pytest from django.test import TestCase as DjangoTestCase from django import http +from django.http import HttpResponse from django.contrib.sessions.middleware import SessionMiddleware from newauth.constants import DEFAULT_USER_PROPERTY from newauth.middleware import AuthMiddleware +def get_response_empty(request): + return HttpResponse() + + @pytest.mark.django_db class MiddlewareTest(DjangoTestCase): fixtures = ['authutils_testdata.json'] def setUp(self): - self.middleware = AuthMiddleware() - self.session_middleware = SessionMiddleware() + self.middleware = AuthMiddleware(get_response_empty) + self.session_middleware = SessionMiddleware(get_response_empty) def test_process_request(self): request = http.HttpRequest() diff --git a/tests/test_views.py b/tests/test_views.py index c01ff4d..aea1ae9 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,6 +1,7 @@ #:coding=utf-8: from urllib.parse import quote import mock +import django from django.test import TestCase as DjangoTestCase from django.contrib.auth import REDIRECT_FIELD_NAME from django.conf import settings @@ -45,7 +46,10 @@ def test_fail_login(self): 'password': 'bad_password', }) self.assertEqual(response.status_code, 200) - self.assertFormError(response, 'form', None, "Please enter a correct username and password. Note that both fields may be case-sensitive.") + if django.VERSION < (5, 0): + self.assertFormError(response, 'form', None, "Please enter a correct username and password. Note that both fields may be case-sensitive.") + else: + self.assertFormError(response.context['form'], None, "Please enter a correct username and password. Note that both fields may be case-sensitive.") def test_fail_login_blank_fields(self): # blank username @@ -54,7 +58,10 @@ def test_fail_login_blank_fields(self): 'password': 'password', }) self.assertEqual(response.status_code, 200) - self.assertFormError(response, 'form', 'username', u'This field is required.') + if django.VERSION < (5, 0): + self.assertFormError(response, 'form', 'username', u'This field is required.') + else: + self.assertFormError(response.context['form'], 'username', u'This field is required.') # blank password response = self.client.post('/account/login/', { @@ -62,7 +69,10 @@ def test_fail_login_blank_fields(self): 'password': '', }) self.assertEqual(response.status_code, 200) - self.assertFormError(response, 'form', 'password', u'This field is required.') + if django.VERSION < (5, 0): + self.assertFormError(response, 'form', 'password', u'This field is required.') + else: + self.assertFormError(response.context['form'], 'password', u'This field is required.') def test_bad_redirect_space(self): bad_next_url = 'test space url' diff --git a/tox.ini b/tox.ini index 125b4ae..1732746 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,8 @@ [tox] envlist = - py{36,37,38,39,310}-dj{22,32} - py{39,310}-djmain + py{38,39,310,311,312}-dj{32,42} + py{310,311,312}-djmain check skipsdist = True @@ -19,8 +19,8 @@ deps = pytest pytest-django pytest-pythonpath - dj22: Django>=2.2,<3.0 dj32: Django>=3.2,<4.0 + dj42: Django>=4.2,<5.0 djmain: https://github.com/django/django/archive/main.tar.gz commands=pytest {posargs} ignore_outcome = @@ -30,16 +30,16 @@ ignore_errors = [gh-actions] python = - 3.6: py36 - 3.7: py37 3.8: py38 3.9: py39 3.10: py310 + 3.11: py311 + 3.12: py312 [gh-actions:env] DJANGO = - 2.2: dj22 3.2: dj32 + 4.2: dj42 main: djmain [testenv:check]