Django 1.11 compatibility fixes.
authorRadek Czajka <rczajka@rczajka.pl>
Wed, 13 Feb 2019 14:38:05 +0000 (15:38 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Wed, 13 Feb 2019 14:38:05 +0000 (15:38 +0100)
CHANGELOG.md
runtests.py
ssify/decorators.py
ssify/middleware_debug.py
ssify/templatetags/ssify.py
ssify/variables.py
ssify/version.py
tests/tests/test_csrf.py
tests/urls.py
tox.ini

index ba5160d..290fd36 100644 (file)
@@ -1,5 +1,9 @@
 # Changelog
 
 # Changelog
 
+## 0.2.6 (2019-02-13)
+
+* Django 1.9-1.11 compatibility.
+
 ## 0.2.5 (2015-04-16)
 
 * Unescape var values in render middleware.
 ## 0.2.5 (2015-04-16)
 
 * Unescape var values in render middleware.
index 4fd6a9d..4c0bdea 100644 (file)
@@ -40,7 +40,17 @@ if not settings.configured and not os.environ.get('DJANGO_SETTINGS_MODULE'):
         ],
         LANGUAGE_CODE='pl',
         MEDIA_URL='/media/',
         ],
         LANGUAGE_CODE='pl',
         MEDIA_URL='/media/',
-        MIDDLEWARE_CLASSES=[
+        MIDDLEWARE_CLASSES=[  # Django < 1.10
+            'django.middleware.csrf.CsrfViewMiddleware',
+            'ssify.middleware.SsiMiddleware',
+            'django.middleware.cache.UpdateCacheMiddleware',
+            'ssify.middleware.PrepareForCacheMiddleware',
+            'django.middleware.common.CommonMiddleware',
+            'django.contrib.sessions.middleware.SessionMiddleware',
+            'ssify.middleware.LocaleMiddleware',
+            'django.middleware.cache.FetchFromCacheMiddleware',
+        ],
+        SMIDDLEWARE = [  # Django < 1.10
             'django.middleware.csrf.CsrfViewMiddleware',
             'ssify.middleware.SsiMiddleware',
             'django.middleware.cache.UpdateCacheMiddleware',
             'django.middleware.csrf.CsrfViewMiddleware',
             'ssify.middleware.SsiMiddleware',
             'django.middleware.cache.UpdateCacheMiddleware',
@@ -53,12 +63,26 @@ if not settings.configured and not os.environ.get('DJANGO_SETTINGS_MODULE'):
         STATIC_URL='/static/',
         ROOT_URLCONF='tests.urls',
         SITE_ID=1,
         STATIC_URL='/static/',
         ROOT_URLCONF='tests.urls',
         SITE_ID=1,
-        TEMPLATE_CONTEXT_PROCESSORS=(
+        TEMPLATE_CONTEXT_PROCESSORS=(  # Django < 1.8
             "django.core.context_processors.debug",
             "django.core.context_processors.i18n",
             "django.core.context_processors.tz",
             "django.core.context_processors.request",
         ),
             "django.core.context_processors.debug",
             "django.core.context_processors.i18n",
             "django.core.context_processors.tz",
             "django.core.context_processors.request",
         ),
+        TEMPLATES = [
+            {
+                'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'APP_DIRS': True,
+                'OPTIONS': {
+                    'context_processors': [
+                        "django.template.context_processors.debug",
+                        "django.template.context_processors.i18n",
+                        "django.template.context_processors.tz",
+                        "django.template.context_processors.request",
+                    ],
+                }
+            },
+        ]
     )
 
 try:
     )
 
 try:
index e2ae9fe..1e2d62a 100644 (file)
@@ -11,7 +11,12 @@ from inspect import getargspec
 import warnings
 from django.conf import settings
 from django.http import Http404
 import warnings
 from django.conf import settings
 from django.http import Http404
-from django.template.base import parse_bits
+try:
+    # Django 1.9
+    from django.template.library import parse_bits
+except ImportError:
+    from django.template.base import parse_bits
+
 from django.utils.translation import get_language, activate
 from .cache import cache_include, DEFAULT_TIMEOUT
 from . import exceptions
 from django.utils.translation import get_language, activate
 from .cache import cache_include, DEFAULT_TIMEOUT
 from . import exceptions
index b0a1e92..f463d53 100644 (file)
@@ -12,10 +12,18 @@ support as a proxy (i.e. Nginx with ssi=on).
 """
 from __future__ import unicode_literals
 import re
 """
 from __future__ import unicode_literals
 import re
+
 try:
     from urllib.parse import urlparse
 except ImportError:
     from urlparse import urlparse
 try:
     from urllib.parse import urlparse
 except ImportError:
     from urlparse import urlparse
+
+try:
+    from django.urls import NoReverseMatch, reverse, resolve
+except ImportError:
+    # Django < 2
+    from django.core.urlresolvers import NoReverseMatch, reverse, resolve
+
 from django.core.urlresolvers import resolve
 from .cache import get_caches
 
 from django.core.urlresolvers import resolve
 from .cache import get_caches
 
index 78071d0..a98a463 100644 (file)
@@ -4,9 +4,15 @@
 #
 from __future__ import absolute_import, unicode_literals
 from django.conf import settings
 #
 from __future__ import absolute_import, unicode_literals
 from django.conf import settings
-from django.core.urlresolvers import NoReverseMatch, reverse, resolve
+try:
+    from django.urls import NoReverseMatch, reverse, resolve
+except ImportError:
+    # Django < 2
+    from django.core.urlresolvers import NoReverseMatch, reverse, resolve
+
 from django.middleware.csrf import get_token, _sanitize_token, rotate_token
 from django import template
 from django.middleware.csrf import get_token, _sanitize_token, rotate_token
 from django import template
+from django.utils.safestring import mark_safe
 from django.utils.translation import get_language
 from ssify.decorators import ssi_variable
 from ssify.utils import ssi_vary_on_cookie
 from django.utils.translation import get_language
 from ssify.decorators import ssi_variable
 from ssify.utils import ssi_vary_on_cookie
@@ -70,7 +76,7 @@ def ssi_include(context, name_, **kwargs):
         request.ssi_patch_response.extend(patch_response)
 
     # Output the SSI include.
         request.ssi_patch_response.extend(patch_response)
 
     # Output the SSI include.
-    return "<!--#include file='%s'-->" % url
+    return mark_safe("<!--#include file='%s'-->" % url)
 
 
 @ssi_variable(register, patch_response=[ssi_vary_on_cookie])
 
 
 @ssi_variable(register, patch_response=[ssi_vary_on_cookie])
index 014e95f..5e220ad 100644 (file)
@@ -12,7 +12,21 @@ at request time to the prerendered templates.
 from __future__ import unicode_literals
 from hashlib import md5
 from django.template import Node
 from __future__ import unicode_literals
 from hashlib import md5
 from django.template import Node
-from django.template.base import get_library
+
+try:
+    # Django < 1.9
+    from django.template.base import get_library
+except:
+    from importlib import import_module
+    from django.template.backends.django import get_installed_libraries
+
+    def get_library(taglib):
+        if not hasattr(get_library, 'libraries'):
+            get_library.libraries = get_installed_libraries()
+        if isinstance(get_library.libraries[taglib], str):
+            get_library.libraries[taglib] = import_module(get_library.libraries[taglib]).register
+        return get_library.libraries[taglib]
+
 from django.utils.encoding import force_text, python_2_unicode_compatible
 from django.utils.functional import Promise
 from django.utils.safestring import mark_safe
 from django.utils.encoding import force_text, python_2_unicode_compatible
 from django.utils.functional import Promise
 from django.utils.safestring import mark_safe
index 0258c9a..2147ed9 100644 (file)
@@ -1,3 +1,3 @@
 from __future__ import unicode_literals
 
 from __future__ import unicode_literals
 
-VERSION = '0.2.5'
+VERSION = '0.2.6'
index 62173ce..8822336 100644 (file)
@@ -4,9 +4,16 @@
 #
 from __future__ import unicode_literals
 
 #
 from __future__ import unicode_literals
 
+import re
 from django.conf import settings
 from django.test import Client, TestCase
 
 from django.conf import settings
 from django.test import Client, TestCase
 
+try:
+    from django.middleware.csrf import _compare_salted_tokens
+except ImportError:
+    # Django < 1.10
+    _compare_salted_tokens = lambda t1, t2: t1 == t2
+
 
 class CsrfTestCase(TestCase):
     def setUp(self):
 
 class CsrfTestCase(TestCase):
     def setUp(self):
@@ -15,24 +22,21 @@ class CsrfTestCase(TestCase):
     def assertCsrfTokenOk(self, response):
         token = response.cookies[settings.CSRF_COOKIE_NAME].value
         self.assertTrue(token)
     def assertCsrfTokenOk(self, response):
         token = response.cookies[settings.CSRF_COOKIE_NAME].value
         self.assertTrue(token)
-        self.assertEqual(
-            response.content.strip(),
-            ("<!--#set var='vd07f6920655622adc90dd591c545bb2a' value='%s'-->\n\n"
-            "<input type='hidden' name='csrfmiddlewaretoken' value='"
-            "<!--#echo var='vd07f6920655622adc90dd591c545bb2a' "
-            "encoding='none'-->' />" % token).encode('ascii')
+        match = re.match(
+            r"<!--#set var='vd07f6920655622adc90dd591c545bb2a' value='([A-Za-z0-9]*)'-->\n\n"
+            r"<input type='hidden' name='csrfmiddlewaretoken' value='"
+            r"<!--#echo var='vd07f6920655622adc90dd591c545bb2a' "
+            r"encoding='none'-->' />",
+            response.content.strip().decode('ascii'),
+            re.MULTILINE
         )
         )
+        self.assertTrue(_compare_salted_tokens(match.group(1), token))
         return token
 
     def test_csrf_token(self):
         response = self.client.get('/csrf')
         token = self.assertCsrfTokenOk(response)
 
         return token
 
     def test_csrf_token(self):
         response = self.client.get('/csrf')
         token = self.assertCsrfTokenOk(response)
 
-        # And now for a second request, with the token cookie.
-        response = self.client.get('/csrf')
-        new_token = self.assertCsrfTokenOk(response)
-        self.assertEqual(new_token, token)
-
         # Make a bad request to see that CSRF protection works.
         response = self.client.post('/csrf_check', {
             'test': 'some data',
         # Make a bad request to see that CSRF protection works.
         response = self.client.post('/csrf_check', {
             'test': 'some data',
index 2c12f8c..2b145cc 100644 (file)
@@ -2,15 +2,15 @@
 # This file is part of django-ssify, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See README.md for more information.
 #
 # This file is part of django-ssify, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See README.md for more information.
 #
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
 
 
-from django.conf.urls import patterns, url
+#from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.views.generic import TemplateView
 from django.views.generic import TemplateView
+from tests import views
 
 
 
 
-urlpatterns = patterns(
-    'tests.views',
-
+urlpatterns = [
     # tests.basic
     url(r'^$',
         TemplateView.as_view(template_name='tests_basic/main.html')
     # tests.basic
     url(r'^$',
         TemplateView.as_view(template_name='tests_basic/main.html')
@@ -21,11 +21,11 @@ urlpatterns = patterns(
     url(r'^basic_include$',
         TemplateView.as_view(template_name='tests_basic/basic_include.html')
         ),
     url(r'^basic_include$',
         TemplateView.as_view(template_name='tests_basic/basic_include.html')
         ),
-    url(r'^random_quote$', 'random_quote', name='random_quote'),
-    url(r'^quote/(?P<number>.+)$', 'quote', name='quote'),
+    url(r'^random_quote$', views.random_quote, name='random_quote'),
+    url(r'^quote/(?P<number>.+)$', views.quote, name='quote'),
 
 
-    url(r'^quote_undeclared/(?P<number>.+)$', 'quote_undeclared'),
-    url(r'^quote_overdeclared/(?P<number>.+)$', 'quote_overdeclared'),
+    url(r'^quote_undeclared/(?P<number>.+)$', views.quote_undeclared),
+    url(r'^quote_overdeclared/(?P<number>.+)$', views.quote_overdeclared),
 
     # tests.args
     url(r'^include_args$',
 
     # tests.args
     url(r'^include_args$',
@@ -35,13 +35,13 @@ urlpatterns = patterns(
         TemplateView.as_view(template_name='tests_args/args.html'),
         {'limit': 3}
         ),
         TemplateView.as_view(template_name='tests_args/args.html'),
         {'limit': 3}
         ),
-    url(r'^args/(?P<limit>\d+)$', 'args', name='args'),
+    url(r'^args/(?P<limit>\d+)$', views.args, name='args'),
 
     # tests.csrf
     url(r'^csrf$',
         TemplateView.as_view(template_name='tests_csrf/csrf_token.html'),
         ),
 
     # tests.csrf
     url(r'^csrf$',
         TemplateView.as_view(template_name='tests_csrf/csrf_token.html'),
         ),
-    url(r'^csrf_check$', 'csrf_check'),
+    url(r'^csrf_check$', views.csrf_check),
 
     # tests.locale
     url(r'^include_language_with_lang$',
 
     # tests.locale
     url(r'^include_language_with_lang$',
@@ -50,12 +50,12 @@ urlpatterns = patterns(
     url(r'^include_language_without_lang$',
         TemplateView.as_view(template_name='tests_locale/include_language_without_lang.html')
         ),
     url(r'^include_language_without_lang$',
         TemplateView.as_view(template_name='tests_locale/include_language_without_lang.html')
         ),
-    url(r'^language/(?P<lang>.+)$', 'language_with_lang', name='language_with_lang'),
-    url(r'^language$', 'language_without_lang', name='language_without_lang'),
-    url(r'^bad_language$', 'language_with_lang', name='bad_language_with_lang'),
+    url(r'^language/(?P<lang>.+)$', views.language_with_lang, name='language_with_lang'),
+    url(r'^language$', views.language_without_lang, name='language_without_lang'),
+    url(r'^bad_language$', views.language_with_lang, name='bad_language_with_lang'),
 
     # tests.render
     url(r'^render$',
         TemplateView.as_view(template_name='tests_render/test_render.html')
         ),
 
     # tests.render
     url(r'^render$',
         TemplateView.as_view(template_name='tests_render/test_render.html')
         ),
-)
+]
diff --git a/tox.ini b/tox.ini
index 063a6b3..b3b729c 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -3,9 +3,12 @@
 #
 [tox]
 envlist=clear,
 #
 [tox]
 envlist=clear,
-    d1{5,6}-py{26,27,32,33,py},
-    d{17,18}-py{27,32,33,34,py},
-    d{d}-py{27,33,34,py},
+    d1{5,6}-py{26,27,32,33},
+    d{17,18}-py{27,32,33,34},
+    d{19,110}-py{27,34,35},
+    d111-py{27,34,35,36,37},
+    #d20-py{34,35,36,37},
+    #d21-py{35,36,37},
     stats
 
 [testenv]
     stats
 
 [testenv]
@@ -16,7 +19,11 @@ deps=
     d16: Django>=1.6,<1.7
     d17: Django>=1.7,<1.8
     d18: Django>=1.8,<1.9
     d16: Django>=1.6,<1.7
     d17: Django>=1.7,<1.8
     d18: Django>=1.8,<1.9
-    dd: https://github.com/django/django/archive/master.tar.gz
+    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
     coverage
 
 [testenv:clear]
     coverage
 
 [testenv:clear]