diff --git a/.travis.yml b/.travis.yml index fe48f33..e014845 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,13 @@ language: python python: 2.7 env: - - TOXENV=py26-14 - - TOXENV=py26-15 - - TOXENV=py26-16 - TOXENV=py27-14 - TOXENV=py27-15 - TOXENV=py27-16 - TOXENV=py27-17 - TOXENV=py27-18 - TOXENV=py27-19 - # Disabling Python 3.2 tests for now as we have Problems with pip 8 on Travis - # - TOXENV=py32-15 - # - TOXENV=py32-16 - # - TOXENV=py32-17 - # - TOXENV=py32-18 - # - TOXENV=py32-18 + - TOXENV=py27-110 - TOXENV=py33-15 - TOXENV=py33-16 - TOXENV=py33-17 @@ -25,14 +17,17 @@ env: - TOXENV=py34-17 - TOXENV=py34-18 - TOXENV=py34-19 + - TOXENV=py34-110 - TOXENV=py35-18 - TOXENV=py35-19 + - TOXENV=py35-110 - TOXENV=pypy-14 - TOXENV=pypy-15 - TOXENV=pypy-16 - TOXENV=pypy-17 - TOXENV=pypy-18 - TOXENV=pypy-19 + - TOXENV=pypy-110 - TOXENV=docs - TOXENV=flake8 before_install: diff --git a/CHANGES.rst b/CHANGES.rst index d71c8eb..c89a42d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,8 +5,12 @@ Changelog ~~~~~~~~~~~~~~~~~~~~~~ * `#176`_: Fix HTML validation for hidden textarea used with GIS widgets. +* `#191`_: Support for Django 1.10. Thanks to MrJmad for the patch. +* `#194`_: Remove official support for Python 2.6 and Python 3.2. .. _#176: https://github.com/gregmuellegger/django-floppyforms/issues/176 +.. _#191: https://github.com/gregmuellegger/django-floppyforms/pull/191 +.. _#194: https://github.com/gregmuellegger/django-floppyforms/pull/194 1.7.0 ~~~~~ diff --git a/docs/index.rst b/docs/index.rst index 2e66eb8..231baa9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -29,7 +29,7 @@ Installation ------------ As a requirement of django-floppyforms, you will need to have Django in -version 1.4 or higher installed and use Python 2.6 or newer. Python 3 and +version 1.4 or higher installed and use Python 2.7 or newer. Python >=3.3 and PyPy are supported! Two-step process to install django-floppyforms: diff --git a/floppyforms/forms.py b/floppyforms/forms.py index f80f2e1..c0f1cb1 100644 --- a/floppyforms/forms.py +++ b/floppyforms/forms.py @@ -38,4 +38,4 @@ class BaseForm(LayoutRenderer, forms.BaseForm): class Form(LayoutRenderer, forms.Form): - pass + use_required_attribute = False diff --git a/floppyforms/templatetags/floppyforms.py b/floppyforms/templatetags/floppyforms.py index b4b223e..b873335 100644 --- a/floppyforms/templatetags/floppyforms.py +++ b/floppyforms/templatetags/floppyforms.py @@ -1,7 +1,9 @@ +import django from collections import defaultdict from contextlib import contextmanager from django.conf import settings + try: from django.forms.utils import ErrorList except ImportError: @@ -36,6 +38,49 @@ def is_bound_field(var): return all(hasattr(var, attr) for attr in significant_attributes) +def raise_or_not_variable_does_not_exist_compat_version(context): + """This function raise exception if template is in debug mode. If not, it return ''. + Multiples ways (depending to the Django version) to retrieve the value of template debug. + + :param context: context for the field. + :return: Either '' or raise Exception + """ + if django.VERSION < (1, 8): + if settings.TEMPLATE_DEBUG: + raise + else: + return '' + + if django.VERSION >= (1, 8) and django.VERSION < (1, 10): + from django.template.engine import Engine + template_debug_value = getattr(settings, 'TEMPLATE_DEBUG', None) + if template_debug_value: + raise + if not template_debug_value: + return '' + if template_debug_value is None: + try: + engine = context.template.engine + except AttributeError: + engine = Engine.get_default() + if engine.debug: + raise + return '' + + if django.VERSION >= (1, 10): + from django.template.engine import Engine + try: + engine = context.template.engine + except AttributeError: + engine = Engine.get_default() + if engine.debug: + raise + + return '' + + raise + + class ConfigFilter(object): """ Can be used as ``filter`` argument to ``FormConfig.configure()``. This @@ -336,17 +381,15 @@ def render(self, context): try: for_ = self.options['for'].resolve(context) except VariableDoesNotExist: - if settings.TEMPLATE_DEBUG: - raise - return '' + return raise_or_not_variable_does_not_exist_compat_version(context) + filter = ConfigFilter(for_) if self.options['using']: try: template_name = self.options['using'].resolve(context) except VariableDoesNotExist: - if settings.TEMPLATE_DEBUG: - raise - return '' + return raise_or_not_variable_does_not_exist_compat_version(context) + config.configure(self.template_config_name, template_name, filter=filter) if self.options['with']: @@ -452,8 +495,17 @@ def get_nodelist(self, context, extra_context): template_name = self.get_template_name(context) return get_template(context, template_name) except: - if settings.TEMPLATE_DEBUG: - raise + if django.VERSION < (1, 10): + if settings.DEBUG: + raise + else: + try: + engine = context.template.engine + except AttributeError: + if settings.DEBUG: + raise + if engine.debug: + raise def get_extra_context(self, context): variables = [] @@ -622,9 +674,7 @@ def render(self, context): try: bound_field = self.variables[0].resolve(context) except VariableDoesNotExist: - if settings.DEBUG: - raise - return '' + return raise_or_not_variable_does_not_exist_compat_version(context) widget = config.retrieve('widget', bound_field=bound_field) extra_context = self.get_extra_context(context) @@ -634,10 +684,7 @@ def render(self, context): try: template_name = self.options['using'].resolve(context) except VariableDoesNotExist: - if settings.DEBUG: - raise - return '' - + return raise_or_not_variable_does_not_exist_compat_version(context) if self.options['only']: context_instance = context.new(extra_context) else: diff --git a/floppyforms/widgets.py b/floppyforms/widgets.py index c890a6e..18b78ce 100644 --- a/floppyforms/widgets.py +++ b/floppyforms/widgets.py @@ -45,6 +45,11 @@ class Widget(forms.Widget): def is_hidden(self): return self.input_type == 'hidden' if hasattr(self, 'input_type') else False + # Backported from Django 1.9 + if not hasattr(forms.Widget, 'format_value'): + def format_value(self, value): + return self._format_value(value) + class Input(Widget): template_name = 'floppyforms/input.html' @@ -89,7 +94,7 @@ def get_context(self, name, value, attrs=None): if value != '': # Only add the value if it is non-empty - context['value'] = self._format_value(value) + context['value'] = self.format_value(value) context.update(self.get_context_data()) context['attrs'] = self.build_attrs(attrs) diff --git a/setup.py b/setup.py index 8eb715d..9adbc89 100644 --- a/setup.py +++ b/setup.py @@ -43,17 +43,17 @@ def find_version(*file_paths): 'Framework :: Django :: 1.7', 'Framework :: Django :: 1.8', 'Framework :: Django :: 1.9', + 'Framework :: Django :: 1.10', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Programming Language :: Python', 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', ], zip_safe=False, ) diff --git a/tests/test_layouts.py b/tests/test_layouts.py index 1764858..7b47a38 100644 --- a/tests/test_layouts.py +++ b/tests/test_layouts.py @@ -7,11 +7,9 @@ from django.utils.translation import ugettext_lazy as _ import floppyforms as forms - from .base import InvalidVariable from .compat import unittest - skipIf = unittest.skipIf @@ -494,13 +492,32 @@ class TemplateStringIfInvalidTests(TestCase): Regression tests for issue #37. ''' def setUp(self): - self.original_TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID + if django.VERSION < (1, 8): + self.original_TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID + else: + self.original_TEMPLATES = settings.TEMPLATES def tearDown(self): - settings.TEMPLATE_STRING_IF_INVALID = self.original_TEMPLATE_STRING_IF_INVALID + if django.VERSION < (1, 8): + settings.TEMPLATE_STRING_IF_INVALID = self.original_TEMPLATE_STRING_IF_INVALID + else: + settings.TEMPLATES = self.original_TEMPLATES + + def set_invalid_string(self, value): + if django.VERSION < (1, 8): + settings.TEMPLATE_STRING_IF_INVALID = value + else: + settings.TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'OPTIONS': { + 'string_if_invalid': value + } + } + ] def test_none(self): - settings.TEMPLATE_STRING_IF_INVALID = None + self.set_invalid_string(None) layout = OneFieldForm().as_p() self.assertHTMLEqual(layout, """ @@ -508,7 +525,7 @@ def test_none(self): """) def test_non_empty(self): - settings.TEMPLATE_STRING_IF_INVALID = InvalidVariable('INVALID') + self.set_invalid_string(InvalidVariable('INVALID')) layout = OneFieldForm().as_p() self.assertHTMLEqual(layout, """ diff --git a/tox.ini b/tox.ini index 233a68f..9fa3ed8 100644 --- a/tox.ini +++ b/tox.ini @@ -3,13 +3,11 @@ minversion = 1.8 envlist = docs, flake8, - py26-{14,15,16}, - py27-{14,15,16,17,18,19}, - py32-{15,16,17,18}, + py27-{14,15,16,17,18,19,110}, py33-{15,16,17,18}, - py34-{15,16,17,18,19}, - py35-{18,19}, - pypy-{14,15,16,17,18,19} + py34-{15,16,17,18,19,110}, + py35-{18,19,110}, + pypy-{14,15,16,17,18,19,110} [testenv] deps = @@ -19,6 +17,7 @@ deps = 17: Django >= 1.7, < 1.8 18: Django >= 1.8, < 1.9 19: Django >= 1.9, < 1.10 + 110: Django >= 1.10, < 1.11 -r{toxinidir}/requirements/tests.txt commands = python runtests.py