Commit abf07355 authored by Vincenzo Pandolfo's avatar Vincenzo Pandolfo Committed by Tim Graham
Browse files

Fixed #26365 -- Added a system check to ensure "string_is_invalid" is a string.

parent efa95397
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import copy

from django.conf import settings
from django.utils import six

from . import Error, Tags, register

@@ -10,6 +13,10 @@ E001 = Error(
    "in OPTIONS. Either remove APP_DIRS or remove the 'loaders' option.",
    id='templates.E001',
)
E002 = Error(
    "'string_if_invalid' in TEMPLATES OPTIONS must be a string but got: {} ({}).",
    id="templates.E002",
)


@register(Tags.templates)
@@ -21,3 +28,15 @@ def check_setting_app_dirs_loaders(app_configs, **kwargs):
        if 'loaders' in conf.get('OPTIONS', {}):
            passed_check = False
    return [] if passed_check else [E001]


@register(Tags.templates)
def check_string_if_invalid_is_string(app_configs, **kwargs):
    errors = []
    for conf in settings.TEMPLATES:
        string_if_invalid = conf.get('OPTIONS', {}).get('string_if_invalid', '')
        if not isinstance(string_if_invalid, six.string_types):
            error = copy.copy(E002)
            error.msg = error.msg.format(string_if_invalid, type(string_if_invalid).__name__)
            errors.append(error)
    return errors
+3 −0
Original line number Diff line number Diff line
@@ -584,6 +584,9 @@ configured:
* **templates.E001**: You have ``'APP_DIRS': True`` in your
  :setting:`TEMPLATES` but also specify ``'loaders'`` in ``OPTIONS``. Either
  remove ``APP_DIRS`` or remove the ``'loaders'`` option.
* **templates.E002**: ``string_if_invalid`` in :setting:`TEMPLATES`
  :setting:`OPTIONS <TEMPLATES-OPTIONS>` must be a string but got: ``{value}``
  (``{type}``).

Caches
------
+57 −2
Original line number Diff line number Diff line
from copy import deepcopy
from copy import copy, deepcopy

from django.core.checks.templates import E001
from django.core.checks.templates import E001, E002
from django.test import SimpleTestCase
from django.test.utils import override_settings

@@ -39,3 +39,58 @@ class CheckTemplateSettingsAppDirsTest(SimpleTestCase):
        del TEMPLATES[0]['OPTIONS']['loaders']
        with self.settings(TEMPLATES=TEMPLATES):
            self.assertEqual(self.func(None), [])


class CheckTemplateStringIfInvalidTest(SimpleTestCase):
    TEMPLATES_STRING_IF_INVALID = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'OPTIONS': {
                'string_if_invalid': False,
            },
        },
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'OPTIONS': {
                'string_if_invalid': 42,
            },
        },
    ]

    @classmethod
    def setUpClass(cls):
        super(CheckTemplateStringIfInvalidTest, cls).setUpClass()
        cls.error1 = copy(E002)
        cls.error2 = copy(E002)
        string_if_invalid1 = cls.TEMPLATES_STRING_IF_INVALID[0]['OPTIONS']['string_if_invalid']
        string_if_invalid2 = cls.TEMPLATES_STRING_IF_INVALID[1]['OPTIONS']['string_if_invalid']
        cls.error1.msg = cls.error1.msg.format(string_if_invalid1, type(string_if_invalid1).__name__)
        cls.error2.msg = cls.error2.msg.format(string_if_invalid2, type(string_if_invalid2).__name__)

    @property
    def func(self):
        from django.core.checks.templates import check_string_if_invalid_is_string
        return check_string_if_invalid_is_string

    @override_settings(TEMPLATES=TEMPLATES_STRING_IF_INVALID)
    def test_string_if_invalid_not_string(self):
        self.assertEqual(self.func(None), [self.error1, self.error2])

    def test_string_if_invalid_first_is_string(self):
        TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
        TEMPLATES[0]['OPTIONS']['string_if_invalid'] = 'test'
        with self.settings(TEMPLATES=TEMPLATES):
            self.assertEqual(self.func(None), [self.error2])

    def test_string_if_invalid_both_are_strings(self):
        TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
        TEMPLATES[0]['OPTIONS']['string_if_invalid'] = 'test'
        TEMPLATES[1]['OPTIONS']['string_if_invalid'] = 'test'
        with self.settings(TEMPLATES=TEMPLATES):
            self.assertEqual(self.func(None), [])

    def test_string_if_invalid_not_specified(self):
        TEMPLATES = deepcopy(self.TEMPLATES_STRING_IF_INVALID)
        del TEMPLATES[1]['OPTIONS']['string_if_invalid']
        with self.settings(TEMPLATES=TEMPLATES):
            self.assertEqual(self.func(None), [self.error1])