Support for Django up to 2.2. 0.4
authorRadek Czajka <rczajka@rczajka.pl>
Wed, 3 Apr 2019 10:14:19 +0000 (12:14 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Wed, 3 Apr 2019 10:14:42 +0000 (12:14 +0200)
`textile` and `pipeline` dependencies are now in extras.
Deprecated `utils.urls.i18n_patterns` and `middleware.URLLocaleMiddleware`,
  as Django 1.10 adds `prefix_default_language` parameter to `i18n_patterns`.
Removed `auth_backends.AttrCASBackend`; use `django-cas-ng` instead.
Added this changelog.

CHANGELOG.md [new file with mode: 0644]
fnpdjango/auth_backends.py [deleted file]
fnpdjango/middleware.py
fnpdjango/templates/fnpdjango/annoy.html
fnpdjango/templatetags/fnp_lang.py
fnpdjango/utils/urls.py
runtests.py
setup.py
tests/tests/__init__.py
tests/tests/test_templatetags_fnp_annoy.py [new file with mode: 0644]
tox.ini

diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644 (file)
index 0000000..7c73ba6
--- /dev/null
@@ -0,0 +1,199 @@
+# Change Log
+
+This document records all notable changes to fnpdjango.
+
+
+## 0.4 (2019-04-03)
+
+- Support for Django up to 2.2.
+- `textile` and `pipeline` dependencies are now in extras.
+- Deprecated `utils.urls.i18n_patterns` and `middleware.URLLocaleMiddleware`,
+  as Django 1.10 adds `prefix_default_language` parameter to `i18n_patterns`.
+- Removed `auth_backends.AttrCASBackend`; use `django-cas-ng` instead.
+- Added this changelog.
+
+
+## 0.3 (2019-02-15)
+
+- Support for Django 1.11.
+- Dropped support for Python 2.6, 3.2, 3.3
+- Removed `prefix` parameter from `utilsurls.i18n_patterns`.
+
+
+## 0.2.8 (2018-07-10)
+
+- Restored `utils.text.char_map`, removed in 0.2 with `slughifi`.
+
+
+## 0.2.7 (2018-01-22)
+
+- Enabled `auto_link` in `utils.text.textilepl.textile_restricted_pl`.
+
+
+## 0.2.6 (2017-07-25)
+
+- Added `utils.fields.TextfileField`.
+
+
+## 0.2.4 (2017-04-05)
+
+- Support for Django 1.10
+- Removed nk.pl from share icons.
+- Updated textile.
+
+
+## 0.2.3 (2017-02-14)
+
+- Fixed import for Django 1.9
+
+
+## 0.2.2 (2016-11-08)
+
+- Fixed bad HTTP 404 in `middleware.URLLocaleMiddleware`.
+
+
+## 0.2.1 (2016-01-04)
+
+- Test with Django up to 1.9.
+
+
+## 0.2 (2014-09-30)
+
+- Removed `utils.text.slughifi`; use `python-slugify` instead.
+- Removed deployment scripts to another package (`fnpdeploy`).
+- Added tests.
+
+
+## 0.1.19-1 (2014-09-01)
+
+- Pinned textile version.
+
+
+## 0.1.19 (2014-06-09)
+
+- `auth_backends.AttrCASBackend`: Save user instance only when necessary.
+- `deploy`: Added `migrate_fake` option.
+- `deploy`: Added root `manage.py` helper script.
+
+
+## 0.1.18 (2014-03-31)
+
+- Added `templatetags.fnp_annoy`.
+
+
+## 0.1.17 (2014-03-27)
+
+- Added `auth_backends.AttrCASBackend`.
+
+
+## 0.1.16 (2014-02-25)
+
+- Added `utils.pipeline_storage.GzipPipelineCachedStorage`.
+
+
+## 0.1.15 (2014-02-14)
+
+- Added `storage.BofhFileSystemStorage`.
+
+
+## 0.1.14 (2014-01-14)
+
+- `deploy`: Fixed gunicorn sample upload when `django_root_path` not set.
+
+
+## 0.1.13 (2014-01-14)
+
+- Enable styling language switcher link depending on the destination language.
+
+
+## 0.1.12 (2014-01-02)
+
+- `deploy`: Added git hash to relase name.
+
+
+## 0.1.11 (2013-12-30)
+
+- Support Django 1.6
+- Minor fixes in deployment and bootstrap scripts.
+
+
+## 0.1.10 (2013-12-12)
+
+- `deploy`: Added `skip_collect_static` option.
+
+
+## 0.1.9.1 (2013-12-06)
+
+- Quick fix for textile.
+
+
+## 0.1.9 (2013-12-06)
+
+- Added `templatetags.fnp_markup.textile_en` and `textile_restricted_en`.
+
+
+## 0.1.8 (2013-11-19)
+
+- Fixed unicode check in slughifi.
+- Fixes for deployment and bootstrap scripts.
+
+
+# 0.1.7 (2013-07-04)
+
+- Fix packaging for `makecontribmessages` command.
+
+Changes in `deploy`:
+- Added `Command` task.
+- Added `pre_collectstatic` hook.
+- Added `django_root_path` and `localsettings_dst_path` options.
+- Auto-install DB requirements.
+- Made `setup` idempotent.
+- Upgrade `git-archive-all.sh` script.
+- Set `SECRET_KEY` on setup.
+- Various minor fixes.
+
+
+## 0.1.6 (2013-03-20)
+- Support for Django 1.5
+
+
+## 0.1.5-1 (2013-02-22)
+
+- Quick fix for previous page link in prevnext.
+
+
+## 0.1.5 (2013-02-22)
+
+- Made prevnext respect current GET parameters.
+- Added a management command for localizing contrib apps.
+- Fixed deployment sudo problem.
+
+
+## 0.1.4 (2013-01-10)
+
+- Added tQ function for filtering translated fields.
+
+
+## 0.1.3 (2013-01-09)
+
+- Fixedd `get_here_url`.
+- Nicer project starter.
+- Fixed deployment scripts.
+
+
+## 0.1.2 (2012-11-30)
+
+- Added app settings.
+- Fixed deployment scripts.
+- Minor fixes.
+
+
+## 0.1.1 (2012-11-22)
+
+- Added deployment scripts.
+- Minor fixes.
+
+
+## 0.1 (2012-11-05)
+
+- Initial release.
diff --git a/fnpdjango/auth_backends.py b/fnpdjango/auth_backends.py
deleted file mode 100644 (file)
index 7a89c1a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-from django.conf import settings
-from django_cas.backends import CASBackend
-
-attr_map = getattr(settings, 'CAS_USER_ATTRS_MAP', {
-    'email': 'email',
-    'firstname': 'first_name',
-    'lastname': 'last_name',
-})
-
-class AttrCASBackend(CASBackend):
-    def authenticate(self, ticket, service, request):
-        user = super(AttrCASBackend, self).authenticate(ticket, service, request)
-        dirty = False
-        for attr, value in request.session.get('attributes', {}).items():
-            try:
-                local_attr = attr_map[attr]
-            except KeyError:
-                pass
-            else:
-                if getattr(user, local_attr, None) != value:
-                    setattr(user, local_attr, value)
-                    dirty = True
-        if dirty:
-            user.save()
-        return user
-
index adf0dc8..734e878 100644 (file)
@@ -1,10 +1,48 @@
-from django.utils import translation
-from django.conf import settings
-from django.http import Http404
 from . import app_settings
 
 from . import app_settings
 
+try:
+    # Django >= 1.10
+    from django.utils.deprecation import MiddlewareMixin
+except ImportError:
+    # Django <= 1.9
+    MiddlewareMixin = object
 
 
-class SetRemoteAddrFromXRealIP(object):
+    from django.conf import settings
+    from django.http import Http404
+    from django.utils import translation
+
+    class URLLocaleMiddleware(MiddlewareMixin):
+        """Decides which translation to use, based on path only."""
+        def process_request(self, request):
+            language = translation.get_language_from_path(request.path_info)
+            if language:
+                translation.activate(language)
+            request.LANGUAGE_CODE = translation.get_language()
+            if language == settings.LANGUAGE_CODE:
+                raise Http404
+
+        def process_response(self, request, response):
+            language = translation.get_language()
+            translation.deactivate()
+            if 'Content-Language' not in response:
+                response['Content-Language'] = language
+            return response
+else:
+    # Django >= 1.10
+    import warnings
+    from django.middleware.locale import LocaleMiddleware
+
+    class URLLocaleMiddleware(LocaleMiddleware):
+        def __init__(self, *args, **kwargs):
+            warnings.warn(
+                "As of Django 1.10, fnpdjango.middleware.URLLocaleMiddleware "
+                "is deprecated in favor of "
+                "django.middleware.locale.LocaleMiddleware.",
+                DeprecationWarning)
+            super(URLLocaleMiddleware, self).__init__(*args, **kwargs)
+
+
+class SetRemoteAddrFromXRealIP(MiddlewareMixin):
     """Sets REMOTE_ADDR from the X-Real-IP header, as set by Nginx."""
     def process_request(self, request):
         if app_settings.REALIP:
     """Sets REMOTE_ADDR from the X-Real-IP header, as set by Nginx."""
     def process_request(self, request):
         if app_settings.REALIP:
@@ -13,22 +51,3 @@ class SetRemoteAddrFromXRealIP(object):
             except KeyError:
                 pass
         return None
             except KeyError:
                 pass
         return None
-
-
-class URLLocaleMiddleware(object):
-    """Decides which translation to use, based on path only."""
-
-    def process_request(self, request):
-        language = translation.get_language_from_path(request.path_info)
-        if language:
-            translation.activate(language)
-        request.LANGUAGE_CODE = translation.get_language()
-        if language == settings.LANGUAGE_CODE:
-            raise Http404
-
-    def process_response(self, request, response):
-        language = translation.get_language()
-        translation.deactivate()
-        if 'Content-Language' not in response:
-            response['Content-Language'] = language
-        return response
index bfec223..996212c 100644 (file)
@@ -1,16 +1,15 @@
-{% load static from staticfiles %}
-<a id='annoy-on' href="http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/">1%</a>
+{% load static from static %}
+<a id='annoy-on' href="https://nowoczesnapolska.org.pl/pomoz-nam/1-procent/">1%</a>
 <div id='annoy'>
 <div id='annoy'>
-    <a href="http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/">
+    <a href="https://nowoczesnapolska.org.pl/pomoz-nam/1-procent/">
         <img src="{% static 'fnpdjango/annoy/procent.png' %}" alt="Logo akcji 1%" /></a>
         <img src="{% static 'fnpdjango/annoy/procent.png' %}" alt="Logo akcji 1%" /></a>
-    <p>Droga użytkowniczko, drogi użytkowniku!</p>
     <p>Fundacja Nowoczesna Polska to
     organizacja pożytku publicznego działająca na rzecz wolności korzystania
     z&nbsp;dóbr kultury. Wesprzyj nasze działania, przeznaczając na nie 1% swojego podatku.
     Możesz to zrobić, wpisując w&nbsp;zeznaniu podatkowym numer
     <strong>KRS&nbsp;0000070056</strong>.</p>
 
     <p>Fundacja Nowoczesna Polska to
     organizacja pożytku publicznego działająca na rzecz wolności korzystania
     z&nbsp;dóbr kultury. Wesprzyj nasze działania, przeznaczając na nie 1% swojego podatku.
     Możesz to zrobić, wpisując w&nbsp;zeznaniu podatkowym numer
     <strong>KRS&nbsp;0000070056</strong>.</p>
 
-    <p><a href="http://nowoczesnapolska.org.pl/pomoz-nam/wesprzyj-nas/">Dowiedz się więcej</a></p>
+    <p><a href="https://nowoczesnapolska.org.pl/pomoz-nam/1-procent/">Dowiedz się więcej</a></p>
     
     <a id='annoy-off'>x</a>
     <div style="clear:both;"></div>
     
     <a id='annoy-off'>x</a>
     <div style="clear:both;"></div>
index 5f7ac24..dd6c339 100644 (file)
@@ -1,5 +1,10 @@
 from django.conf import settings
 from django.conf import settings
-from django.core.urlresolvers import resolve, reverse, Resolver404
+
+try:
+    from django.urls import resolve, reverse, Resolver404
+except ImportError:
+    from django.core.urlresolvers import resolve, reverse, Resolver404
+
 from django import template
 from django.utils import translation
 from ..utils.views import get_current_object
 from django import template
 from django.utils import translation
 from ..utils.views import get_current_object
index a493c97..4e9916f 100644 (file)
@@ -2,38 +2,50 @@
 Utilities for urlconfs.
 """
 
 Utilities for urlconfs.
 """
 
-import re
-from django.conf import settings
-from django.core.urlresolvers import LocaleRegexURLResolver
-from django.utils.translation import get_language
+import django
+if django.VERSION >= (1, 10):
+    import warnings
+    from django.conf.urls.i18n import i18n_patterns as django_i18n_patterns
 
 
+    def i18n_patterns(*args):
+        warnings.warn(
+            "As of Django 1.10, fnpdjango.utils.urls.i18n_patterns "
+            "is deprecated in favor of directly using "
+            "django.urls.i18n_patterns(prefix_default_language=False).",
+            DeprecationWarning)
+        return django_i18n_patterns(*args, prefix_default_language=False)
 
 
-class MyLocaleRegexURLResolver(LocaleRegexURLResolver):
-    """
-    A URL resolver that always matches the active language code as URL prefix.
+else:
+    # Django <= 1.9
+    import re
+    from django.conf import settings
+    from django.core.urlresolvers import LocaleRegexURLResolver
+    from django.utils.translation import get_language
 
 
-    Rather than taking a regex argument, we just override the ``regex``
-    function to always return the active language-code as regex.
-    """
-    @property
-    def regex(self):
-        language_code = get_language()
-        if language_code == settings.LANGUAGE_CODE:
-            return re.compile('')
-        if language_code not in self._regex_dict:
-            regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
-            self._regex_dict[language_code] = regex_compiled
-        return self._regex_dict[language_code]
+    class MyLocaleRegexURLResolver(LocaleRegexURLResolver):
+        """
+        A URL resolver that always matches the active language code as URL prefix.
 
 
+        Rather than taking a regex argument, we just override the ``regex``
+        function to always return the active language-code as regex.
+        """
+        @property
+        def regex(self):
+            language_code = get_language()
+            if language_code == settings.LANGUAGE_CODE:
+                return re.compile('')
+            if language_code not in self._regex_dict:
+                regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
+                self._regex_dict[language_code] = regex_compiled
+            return self._regex_dict[language_code]
 
 
-def i18n_patterns(*args):
-    """
-    Adds the language code prefix to every URL pattern within this
-    function. This may only be used in the root URLconf, not in an included
-    URLconf.
-
-    """
-    pattern_list = list(args)
-    if not settings.USE_I18N:
-        return pattern_list
-    return pattern_list + [MyLocaleRegexURLResolver(pattern_list)]
+    def i18n_patterns(*args):
+        """
+        Adds the language code prefix to every URL pattern within this
+        function. This may only be used in the root URLconf, not in an included
+        URLconf.
+        """
+        pattern_list = list(args)
+        if not settings.USE_I18N:
+            return pattern_list
+        return pattern_list + [MyLocaleRegexURLResolver(pattern_list)]
index 3f8dd95..28648cf 100644 (file)
@@ -41,7 +41,13 @@ if not settings.configured and not os.environ.get('DJANGO_SETTINGS_MODULE'):
         ],
         LANGUAGE_CODE='pl',
         MEDIA_ROOT=media_root,
         ],
         LANGUAGE_CODE='pl',
         MEDIA_ROOT=media_root,
-        MIDDLEWARE_CLASSES=[
+        STATIC_URL='/static/',
+        MIDDLEWARE_CLASSES=[    # Django <= 1.9
+            'django.middleware.common.CommonMiddleware',
+            'fnpdjango.middleware.URLLocaleMiddleware',
+            'fnpdjango.middleware.SetRemoteAddrFromXRealIP',
+        ],
+        MIDDLEWARE=[
             'django.middleware.common.CommonMiddleware',
             'fnpdjango.middleware.URLLocaleMiddleware',
             'fnpdjango.middleware.SetRemoteAddrFromXRealIP',
             'django.middleware.common.CommonMiddleware',
             'fnpdjango.middleware.URLLocaleMiddleware',
             'fnpdjango.middleware.SetRemoteAddrFromXRealIP',
@@ -51,6 +57,7 @@ if not settings.configured and not os.environ.get('DJANGO_SETTINGS_MODULE'):
         TEMPLATES=[
             {
                 'BACKEND': 'django.template.backends.django.DjangoTemplates',
         TEMPLATES=[
             {
                 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+                'APP_DIRS': True,
             },
         ],
         TEST_LAZY_UGETTEXT_LAZY=_("Lazy setting."),
             },
         ],
         TEST_LAZY_UGETTEXT_LAZY=_("Lazy setting."),
index adb30aa..c0775b7 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -23,7 +23,7 @@ def whole_trees(package_dir, paths):
 
 setup(
     name='fnpdjango',
 
 setup(
     name='fnpdjango',
-    version='0.3',
+    version='0.4',
     author='Radek Czajka',
     author_email='radekczajka@nowoczesnapolska.org.pl',
     url='',
     author='Radek Czajka',
     author_email='radekczajka@nowoczesnapolska.org.pl',
     url='',
@@ -33,9 +33,16 @@ setup(
         'fnpdjango.management.commands': ['babel.cfg'],
     },
     install_requires=[
         'fnpdjango.management.commands': ['babel.cfg'],
     },
     install_requires=[
-        'Django>=1.4,<2.0',
-        'textile==2.3.16',
+        'Django>=1.4,<2.3',
     ],
     ],
+    extras_require={
+        'textile': [
+            'textile==2.3.16',
+        ],
+        'pipeline': [
+            'pipeline',
+        ],
+    },
     license='LICENSE',
     description='.',
     long_description="",
     license='LICENSE',
     description='.',
     long_description="",
index 468aae5..7801a8c 100644 (file)
@@ -10,6 +10,7 @@ test_* modules by itself.
 """
 from .test_middleware import *
 from .test_storage import *
 """
 from .test_middleware import *
 from .test_storage import *
+from .test_templatetags_fnp_annoy import *
 from .test_templatetags_fnp_markup import *
 from .test_templatetags_macros import *
 from .test_utils_settings import *
 from .test_templatetags_fnp_markup import *
 from .test_templatetags_macros import *
 from .test_utils_settings import *
diff --git a/tests/tests/test_templatetags_fnp_annoy.py b/tests/tests/test_templatetags_fnp_annoy.py
new file mode 100644 (file)
index 0000000..8ed80b1
--- /dev/null
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# This file is part of FNPDjango, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See README.md for more information.
+#
+from __future__ import unicode_literals
+
+from django.test import TestCase
+from django.test.utils import override_settings
+
+
+class TemplatetagsFNPAnnoyTestCase(TestCase):
+
+    def test_annoy(self):
+        from fnpdjango.templatetags import fnp_annoy
+        self.assertEqual(
+            fnp_annoy.annoy(),
+            '')
+        with override_settings(FNP_ANNOY=True):
+            self.assertTrue(
+                'https://nowoczesnapolska.org.pl/pomoz-nam/1-procent/'
+                in fnp_annoy.annoy()
+            )
diff --git a/tox.ini b/tox.ini
index 2175e7c..5e71cfb 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -7,8 +7,8 @@ envlist=clear,
     d17-py{27,34},
     d{18,19,110}-py{27,34,35},
     d111-py{27,34,35,36,37},
     d17-py{27,34},
     d{18,19,110}-py{27,34,35},
     d111-py{27,34,35,36,37},
-    #d20-py{34,35,36,37},
-    #d21-py{35,36,37},
+    d20-py{34,35,36,37},
+    d{21,22}-py{35,36,37},
     stats
 
 [testenv]
     stats
 
 [testenv]
@@ -25,6 +25,8 @@ deps=
     d20: Django>=2.0,<2.1
     d21: Django>=2.1,<2.2
     coverage
     d20: Django>=2.0,<2.1
     d21: Django>=2.1,<2.2
     coverage
+extras=
+    textile
 
 [testenv:clear]
 basepython=python3.4
 
 [testenv:clear]
 basepython=python3.4