Support for Django up to 3.1. Dropped support for Django<1.10 and Python<3.5.
authorRadek Czajka <rczajka@rczajka.pl>
Tue, 30 Mar 2021 10:11:03 +0000 (12:11 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Tue, 30 Mar 2021 10:11:03 +0000 (12:11 +0200)
15 files changed:
cas_provider/__init__.py
cas_provider/admin.py
cas_provider/attribute_formatters.py
cas_provider/forms.py
cas_provider/management/commands/cleanuptickets.py
cas_provider/models.py
cas_provider/signals.py
cas_provider/urls.py
cas_provider/views.py
cas_provider_examples/manage.py
cas_provider_examples/simple/settings.py
cas_provider_examples/simple/tests.py
cas_provider_examples/simple/urls.py
setup.py
tox.ini

index ff16364..22cedc3 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf import settings
 
 __all__ = []
 from django.conf import settings
 
 __all__ = []
index 075fcb9..90182e2 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.contrib import admin
 from .models import *
 
 from django.contrib import admin
 from .models import *
 
index 8574962..45a2403 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from lxml import etree
 import collections
 
 from lxml import etree
 import collections
 
index e4df105..7f3d5b6 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 
index 994c766..6715151 100644 (file)
@@ -6,8 +6,6 @@ Calls ``ServiceTickets.objects.delete_expired_users()``, which
 contains the actual logic for determining which accounts are deleted.
 
 """
 contains the actual logic for determining which accounts are deleted.
 
 """
-from __future__ import print_function, unicode_literals
-
 from django.core.management.base import NoArgsCommand
 from django.conf import settings
 
 from django.core.management.base import NoArgsCommand
 from django.conf import settings
 
index 14c2294..4a38927 100644 (file)
@@ -1,16 +1,10 @@
-from __future__ import unicode_literals
-
 from django.conf import settings
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from random import Random
 import string
 from django.conf import settings
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from random import Random
 import string
-try:
-    from urllib.parse import urlencode, urlparse, parse_qs, ParseResult
-except ImportError:
-    from urllib import urlencode
-    from urlparse import urlparse, ParseResult
-    from urlparse import parse_qs
+from urllib.parse import urlencode, urlparse, parse_qs, ParseResult
+
 
 __all__ = ['ServiceTicket', 'LoginTicket', 'ProxyGrantingTicket', 'ProxyTicket', 'ProxyGrantingTicketIOU']
 
 
 __all__ = ['ServiceTicket', 'LoginTicket', 'ProxyGrantingTicket', 'ProxyTicket', 'ProxyGrantingTicketIOU']
 
index 3c469db..b263078 100644 (file)
@@ -1,8 +1,5 @@
-# -*- coding: utf-8 -*-
 """cas_provider.signals -- signal definitions for cas_provider
 """
 """cas_provider.signals -- signal definitions for cas_provider
 """
-from __future__ import unicode_literals
-
 from django import dispatch
 
 
 from django import dispatch
 
 
index f679a87..9f6304b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import url
 from cas_provider import views
 
 from django.conf.urls import url
 from cas_provider import views
 
index ccf84a2..6b39131 100644 (file)
@@ -1,20 +1,11 @@
-from __future__ import unicode_literals
-
 import logging
 logger = logging.getLogger('cas_provider.views')
 
 import logging
 logger = logging.getLogger('cas_provider.views')
 
-try:
-    from urllib.error import HTTPError, URLError
-    from urllib.parse import parse_qsl, urlencode, urlparse, urlsplit, urlunsplit
-    from urllib.request import urlopen
-except ImportError:
-    from urllib import urlencode
-    from urllib2 import HTTPError, URLError, urlopen
-    from urlparse import parse_qsl, urlparse, urlsplit, urlunsplit
+from urllib.error import HTTPError, URLError
+from urllib.parse import parse_qsl, urlencode, urlparse, urlsplit, urlunsplit
+from urllib.request import urlopen
 from functools import wraps
 
 from functools import wraps
 
-from django import VERSION
-from django.utils.decorators import available_attrs
 from django.views.decorators.debug import sensitive_post_parameters
 from django.views.decorators.cache import cache_control
 from django.utils.cache import patch_cache_control
 from django.views.decorators.debug import sensitive_post_parameters
 from django.views.decorators.cache import cache_control
 from django.utils.cache import patch_cache_control
@@ -39,12 +30,7 @@ from cas_provider.forms import LoginForm, MergeLoginForm
 
 from . import signals
 
 
 from . import signals
 
-if VERSION >= (1, 10):
-    from django.urls import get_callable, reverse
-    user_is_authenticated = lambda user: user.is_authenticated
-else:
-    from django.core.urlresolvers import get_callable, reverse
-    user_is_authenticated = lambda user: user.is_authenticated()
+from django.urls import get_callable, reverse
 
 __all__ = ['login', 'validate', 'logout', 'service_validate']
 
 
 __all__ = ['login', 'validate', 'logout', 'service_validate']
 
@@ -72,7 +58,7 @@ def never_cache(view_func):
     Decorator that adds headers to a response so that it will
     never be cached.
     """
     Decorator that adds headers to a response so that it will
     never be cached.
     """
-    @wraps(view_func, assigned=available_attrs(view_func))
+    @wraps(view_func)
     def _wrapped_view_func(request, *args, **kwargs):
         response = view_func(request, *args, **kwargs)
         patch_cache_control(response, no_cache=True,
     def _wrapped_view_func(request, *args, **kwargs):
         response = view_func(request, *args, **kwargs)
         patch_cache_control(response, no_cache=True,
@@ -150,7 +136,7 @@ def login(request, template_name='cas/login.html',
         else:
             form = LoginForm(initial={'service': service})
 
         else:
             form = LoginForm(initial={'service': service})
 
-    if user is not None and user_is_authenticated(user):
+    if user is not None and user.is_authenticated:
         # We have an authenticated user.
         if not user.is_active:
             errors.append(_('This account is disabled. Please contact us if you feel it should be enabled again.'))
         # We have an authenticated user.
         if not user.is_active:
             errors.append(_('This account is disabled. Please contact us if you feel it should be enabled again.'))
@@ -227,7 +213,7 @@ def validate(request):
 def logout(request, template_name='cas/logout.html',
            auto_redirect=settings.CAS_AUTO_REDIRECT_AFTER_LOGOUT):
     url = request.GET.get('url', None)
 def logout(request, template_name='cas/logout.html',
            auto_redirect=settings.CAS_AUTO_REDIRECT_AFTER_LOGOUT):
     url = request.GET.get('url', None)
-    if user_is_authenticated(request.user):
+    if request.user.is_authenticated:
         for ticket in ServiceTicket.objects.filter(user=request.user):
             ticket.delete()
         auth_logout(request)
         for ticket in ServiceTicket.objects.filter(user=request.user):
             ticket.delete()
         auth_logout(request)
index a2aa65d..fc99637 100755 (executable)
@@ -1,6 +1,4 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
-from __future__ import unicode_literals
-
 import os
 import sys
 
 import os
 import sys
 
index 6a520b4..8cf53ed 100644 (file)
@@ -1,7 +1,3 @@
-from __future__ import unicode_literals
-
-from django import VERSION
-
 # Django settings for xxx project.
 
 DEBUG = True
 # Django settings for xxx project.
 
 DEBUG = True
@@ -99,8 +95,6 @@ MIDDLEWARE = (
     'django.contrib.messages.middleware.MessageMiddleware',
 )
 
     'django.contrib.messages.middleware.MessageMiddleware',
 )
 
-# For Django < 1.10
-MIDDLEWARE_CLASSES = MIDDLEWARE
 
 
 ROOT_URLCONF = 'simple.urls'
 
 
 ROOT_URLCONF = 'simple.urls'
index 6518bdf..4e8b05e 100644 (file)
@@ -1,5 +1,6 @@
-from __future__ import unicode_literals
 from io import StringIO
 from io import StringIO
+from urllib.parse import urlparse, parse_qsl, parse_qs
+from urllib.request import install_opener
 from xml import etree
 from xml.etree import ElementTree
 import cas_provider
 from xml import etree
 from xml.etree import ElementTree
 import cas_provider
@@ -10,23 +11,7 @@ from cas_provider.views import _cas2_sucess_response, INVALID_TICKET, _cas2_erro
 from django.contrib.auth.models import User, UserManager
 from django.test import TestCase
 from django.conf import settings
 from django.contrib.auth.models import User, UserManager
 from django.test import TestCase
 from django.conf import settings
-from django import VERSION
-
-
-try:
-    from urllib.parse import urlparse, parse_qsl, parse_qs
-    from urllib.request import install_opener
-except:
-    from urlparse import urlparse, parse_qsl, parse_qs
-    from urllib2 import install_opener
-
-
-if VERSION >= (1, 10):
-    from django.urls import reverse
-    user_is_anonymous = lambda user: user.is_anonymous
-else:
-    from django.core.urlresolvers import reverse
-    user_is_anonymous = lambda user: user.is_anonymous()
+from django.urls import reverse
 
 
 class DummyOpener(object):
 
 
 class DummyOpener(object):
@@ -140,7 +125,7 @@ class ViewsTest(TestCase):
         self.assertIsNotNone(proxyTicketResponseXml_2.find(CAS + "proxySuccess/" + CAS + "proxyTicket"))
         proxyTicket_2 = proxyTicketResponseXml_2.find(CAS + "proxySuccess/" + CAS + "proxyTicket")
 
         self.assertIsNotNone(proxyTicketResponseXml_2.find(CAS + "proxySuccess/" + CAS + "proxyTicket"))
         proxyTicket_2 = proxyTicketResponseXml_2.find(CAS + "proxySuccess/" + CAS + "proxyTicket")
 
-        proxyValidateResponse_3 = self.client.get(reverse('cas_proxy_validate'), {'ticket': proxyTicket_2.text, 'service': proxyTarget_2, 'pgtUrl': None})
+        proxyValidateResponse_3 = self.client.get(reverse('cas_proxy_validate'), {'ticket': proxyTicket_2.text, 'service': proxyTarget_2, 'pgtUrl': ''})
         proxyValidateResponseXml_3 = ElementTree.parse(StringIO(proxyValidateResponse_3.content.decode('utf-8')))
 
         auth_success_3 = proxyValidateResponseXml_3.find(CAS + 'authenticationSuccess')
         proxyValidateResponseXml_3 = ElementTree.parse(StringIO(proxyValidateResponse_3.content.decode('utf-8')))
 
         auth_success_3 = proxyValidateResponseXml_3.find(CAS + 'authenticationSuccess')
@@ -155,8 +140,6 @@ class ViewsTest(TestCase):
         self.assertEqual('root', user_3.text)
 
 
         self.assertEqual('root', user_3.text)
 
 
-
-    
     def test_succeessful_login(self):
         response = self._login_user('root', '123')
         self._validate_cas1(response, True)
     def test_succeessful_login(self):
         response = self._login_user('root', '123')
         self._validate_cas1(response, True)
@@ -167,7 +150,7 @@ class ViewsTest(TestCase):
 
         response = self.client.get(reverse('cas_login'), follow=False)
         self.assertEqual(response.status_code, 302)
 
         response = self.client.get(reverse('cas_login'), follow=False)
         self.assertEqual(response.status_code, 302)
-        self.assertTrue(response['location'].startswith('http://testserver/' if VERSION < (1, 9) else '/'))
+        self.assertTrue(response['location'].startswith('/'))
 
         response = self.client.get(response['location'], follow=False)
         self.assertIn(response.status_code, [302, 200])
 
         response = self.client.get(response['location'], follow=False)
         self.assertIn(response.status_code, [302, 200])
@@ -190,7 +173,7 @@ class ViewsTest(TestCase):
 
         response = self.client.get(reverse('cas_login'), follow=False)
         self.assertEqual(response.status_code, 200)
 
         response = self.client.get(reverse('cas_login'), follow=False)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(user_is_anonymous(response.context['user']), True)
+        self.assertTrue(response.context['user'].is_anonymous)
 
 
     def test_broken_pwd(self):
 
 
     def test_broken_pwd(self):
index 62e735d..d13d505 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import unicode_literals
-
 from django.conf.urls import include, url
 from django.contrib import admin
 from django.views.generic import TemplateView
 from django.conf.urls import include, url
 from django.contrib import admin
 from django.views.generic import TemplateView
index 60c37c8..3372d35 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ setup(
     long_description=read('README.rst'),
     zip_safe=False,
     install_requires=[
     long_description=read('README.rst'),
     zip_safe=False,
     install_requires=[
-        'Django>=1.5,<2.2',
+        'Django>=1.10,<3.2',
         'lxml',
         ],
     classifiers = [
         'lxml',
         ],
     classifiers = [
diff --git a/tox.ini b/tox.ini
index 4344927..9dc49ee 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,22 +1,24 @@
 [tox]
 envlist=clear,
 [tox]
 envlist=clear,
-    d18-py{27,34},
-    d{19,110}-py{27,34,35},
-    d111-py{27,34,35,36,37},
-    d20-py{34,35,36,37},
+    d110-py{35},
+    d111-py{35,36,37},
+    d20-py{35,36,37},
     d21-py{35,36,37},
     d21-py{35,36,37},
+    d22-py{35,36,37,38,39}
+    d{30,31}-py{36,37,38,39}
     stats
 
 [testenv]
 commands=coverage run --source=cas_provider --append --branch cas_provider_examples/manage.py test simple
 deps=
     stats
 
 [testenv]
 commands=coverage run --source=cas_provider --append --branch cas_provider_examples/manage.py test simple
 deps=
-    d18: Django>=1.8,<1.9
     d19: Django>=1.9,<1.10
     d110: Django>=1.10,<1.11
     d111: Django>=1.11,<2.0
     d20: Django>=2.0,<2.1
     d21: Django>=2.1,<2.2
     d19: Django>=1.9,<1.10
     d110: Django>=1.10,<1.11
     d111: Django>=1.11,<2.0
     d20: Django>=2.0,<2.1
     d21: Django>=2.1,<2.2
-    d15,d16: https://bitbucket.org/andrewgodwin/south/get/e2c9102ee033.zip
+    d22: Django>=2.2,<3.0
+    d30: Django>=3.0,<3.1
+    d31: Django>=3.1,<3.2
     coverage
 usedevelop=True
 
     coverage
 usedevelop=True