diff --git a/django/template/__init__.py b/django/template/__init__.py index 63b3d7ba4d..092bd5663c 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -58,7 +58,8 @@ from .exceptions import TemplateDoesNotExist, TemplateSyntaxError # NOQA i # Template parts from .base import ( # NOQA isort:skip - Context, Node, NodeList, Origin, RequestContext, Template, Variable, + Context, Node, NodeList, Origin, RequestContext, StringOrigin, Template, + Variable, ) # Deprecated in Django 1.8, will be removed in Django 1.10. diff --git a/django/template/base.py b/django/template/base.py index 52586e7ab5..530b60a3a9 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -60,7 +60,10 @@ from django.template.context import ( # NOQA: imported for backwards compatibil BaseContext, Context, ContextPopException, RequestContext, ) from django.utils import six -from django.utils.deprecation import RemovedInDjango110Warning +from django.utils.deprecation import ( + DeprecationInstanceCheck, RemovedInDjango20Warning, + RemovedInDjango110Warning, +) from django.utils.encoding import ( force_str, force_text, python_2_unicode_compatible, ) @@ -158,6 +161,11 @@ class Origin(object): ) +class StringOrigin(six.with_metaclass(DeprecationInstanceCheck, Origin)): + alternative = 'django.template.Origin' + deprecation_warning = RemovedInDjango20Warning + + class Template(object): def __init__(self, template_string, origin=None, name=None, engine=None): try: diff --git a/django/template/loader.py b/django/template/loader.py index ed3039b471..8a344cd983 100644 --- a/django/template/loader.py +++ b/django/template/loader.py @@ -1,9 +1,14 @@ import warnings -from django.utils.deprecation import RemovedInDjango110Warning +from django.utils import six +from django.utils.deprecation import ( + DeprecationInstanceCheck, RemovedInDjango20Warning, + RemovedInDjango110Warning, +) from . import engines from .backends.django import DjangoTemplates +from .base import Origin from .engine import ( _context_instance_undefined, _dictionary_undefined, _dirs_undefined, ) @@ -147,3 +152,8 @@ class BaseLoader(base.Loader): "django.template.loaders.base.Loader.", RemovedInDjango110Warning, stacklevel=2) super(BaseLoader, self).__init__(*args, **kwargs) + + +class LoaderOrigin(six.with_metaclass(DeprecationInstanceCheck, Origin)): + alternative = 'django.template.Origin' + deprecation_warning = RemovedInDjango20Warning diff --git a/django/utils/deprecation.py b/django/utils/deprecation.py index df2f701b71..75270a81ef 100644 --- a/django/utils/deprecation.py +++ b/django/utils/deprecation.py @@ -73,3 +73,12 @@ class RenameMethodsBase(type): setattr(base, old_method_name, wrapper(new_method)) return new_class + + +class DeprecationInstanceCheck(type): + def __instancecheck__(self, instance): + warnings.warn( + "`%s` is deprecated, use `%s` instead." % (self.__name__, self.alternative), + self.deprecation_warning, 2 + ) + return super(DeprecationInstanceCheck, self).__instancecheck__(instance) diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 8b9ab3254c..d356ecb2f3 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -100,6 +100,10 @@ details on these changes. * The ``enclosure`` keyword argument to ``SyndicationFeed.add_item()`` will be removed. +* The ``django.template.loader.LoaderOrigin`` and + ``django.template.base.StringOrigin`` aliases for + ``django.template.base.Origin`` will be removed. + .. _deprecation-removed-in-1.10: 1.10 diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index c63ae1c351..1f8a127c4f 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -818,7 +818,9 @@ debug as ``True``, an instance of ``django.template.loader.LoaderOrigin`` or ``django.template.base.StringOrigin`` was set as the origin attribute on the template object. These classes have been combined into :class:`~django.template.base.Origin` and is now always set regardless of the -engine debug setting. +engine debug setting. For a minimal level of backwards compatibility, the old +class names will be kept as aliases to the new ``Origin`` class until +Django 2.0. .. _default-logging-changes-19: @@ -1335,6 +1337,10 @@ Miscellaneous deprecated. Use the new ``enclosures`` argument which accepts a list of ``Enclosure`` objects instead of a single one. +* The ``django.template.loader.LoaderOrigin`` and + ``django.template.base.StringOrigin`` aliases for + ``django.template.base.Origin`` are deprecated. + .. _removed-features-1.9: Features removed in 1.9 diff --git a/tests/deprecation/tests.py b/tests/deprecation/tests.py index 8f4ccf4eb5..6fa53a7fa0 100644 --- a/tests/deprecation/tests.py +++ b/tests/deprecation/tests.py @@ -7,7 +7,9 @@ import warnings from django.test import SimpleTestCase from django.test.utils import reset_warning_registry from django.utils import six -from django.utils.deprecation import RenameMethodsBase +from django.utils.deprecation import ( + DeprecationInstanceCheck, RemovedInNextVersionWarning, RenameMethodsBase, +) from django.utils.encoding import force_text @@ -197,3 +199,16 @@ class DeprecatingSimpleTestCaseUrls(unittest.TestCase): "SimpleTestCase.urls is deprecated and will be removed in " "Django 1.10. Use @override_settings(ROOT_URLCONF=...) " "in TempTestCase instead.") + + +class DeprecationInstanceCheckTest(SimpleTestCase): + def test_warning(self): + class Manager(six.with_metaclass(DeprecationInstanceCheck)): + alternative = 'fake.path.Foo' + deprecation_warning = RemovedInNextVersionWarning + + msg = '`Manager` is deprecated, use `fake.path.Foo` instead.' + with warnings.catch_warnings(): + warnings.simplefilter('error', category=RemovedInNextVersionWarning) + with self.assertRaisesMessage(RemovedInNextVersionWarning, msg): + isinstance(object, Manager)