Loading django/template/backends/django.py +24 −6 Original line number Diff line number Diff line # Since this package contains a "django" module, this is required on Python 2. from __future__ import absolute_import import sys import warnings from django.conf import settings from django.template import TemplateDoesNotExist from django.template.context import Context, RequestContext, make_context from django.template.engine import Engine, _dirs_undefined from django.utils import six from django.utils.deprecation import RemovedInDjango20Warning from .base import BaseEngine Loading @@ -24,21 +27,23 @@ class DjangoTemplates(BaseEngine): self.engine = Engine(self.dirs, self.app_dirs, **options) def from_string(self, template_code): return Template(self.engine.from_string(template_code)) return Template(self.engine.from_string(template_code), self) def get_template(self, template_name, dirs=_dirs_undefined): return Template(self.engine.get_template(template_name, dirs)) try: return Template(self.engine.get_template(template_name, dirs), self) except TemplateDoesNotExist as exc: reraise(exc, self) class Template(object): def __init__(self, template): def __init__(self, template, backend): self.template = template self.backend = backend @property def origin(self): # TODO: define the Origin API. For now simply forwarding to the # underlying Template preserves backwards-compatibility. return self.template.origin def render(self, context=None, request=None): Loading Loading @@ -71,4 +76,17 @@ class Template(object): else: context = make_context(context, request) try: return self.template.render(context) except TemplateDoesNotExist as exc: reraise(exc, self.backend) def reraise(exc, backend): """ Reraise TemplateDoesNotExist while maintaining template debug information. """ new = exc.__class__(*exc.args, tried=exc.tried, backend=backend) if hasattr(exc, 'template_debug'): new.template_debug = exc.template_debug six.reraise(exc.__class__, new, sys.exc_info()[2]) django/template/backends/dummy.py +12 −4 Original line number Diff line number Diff line # Since this package contains a "django" module, this is required on Python 2. from __future__ import absolute_import import errno import io import string from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.template import TemplateDoesNotExist from django.template import Origin, TemplateDoesNotExist from django.utils.html import conditional_escape from .base import BaseEngine Loading @@ -29,17 +30,24 @@ class TemplateStrings(BaseEngine): return Template(template_code) def get_template(self, template_name): tried = [] for template_file in self.iter_template_filenames(template_name): try: with io.open(template_file, encoding=settings.FILE_CHARSET) as fp: template_code = fp.read() except IOError: except IOError as e: if e.errno == errno.ENOENT: tried.append(( Origin(template_file, template_name, self), 'Source does not exist', )) continue raise return Template(template_code) else: raise TemplateDoesNotExist(template_name) raise TemplateDoesNotExist(template_name, tried=tried, backend=self) class Template(string.Template): Loading django/template/backends/jinja2.py +48 −4 Original line number Diff line number Diff line Loading @@ -41,17 +41,24 @@ class Jinja2(BaseEngine): try: return Template(self.env.get_template(template_name)) except jinja2.TemplateNotFound as exc: six.reraise(TemplateDoesNotExist, TemplateDoesNotExist(exc.args), sys.exc_info()[2]) six.reraise( TemplateDoesNotExist, TemplateDoesNotExist(exc.name, backend=self), sys.exc_info()[2], ) except jinja2.TemplateSyntaxError as exc: six.reraise(TemplateSyntaxError, TemplateSyntaxError(exc.args), sys.exc_info()[2]) new = TemplateSyntaxError(exc.args) new.template_debug = get_exception_info(exc) six.reraise(TemplateSyntaxError, new, sys.exc_info()[2]) class Template(object): def __init__(self, template): self.template = template self.origin = Origin( name=template.filename, template_name=template.name, ) def render(self, context=None, request=None): if context is None: Loading @@ -61,3 +68,40 @@ class Template(object): context['csrf_input'] = csrf_input_lazy(request) context['csrf_token'] = csrf_token_lazy(request) return self.template.render(context) class Origin(object): """ A container to hold debug information as described in the template API documentation. """ def __init__(self, name, template_name): self.name = name self.template_name = template_name def get_exception_info(exception): """ Formats exception information for display on the debug page using the structure described in the template API documentation. """ context_lines = 10 lineno = exception.lineno lines = list(enumerate(exception.source.strip().split("\n"), start=1)) during = lines[lineno - 1][1] total = len(lines) top = max(0, lineno - context_lines - 1) bottom = min(total, lineno + context_lines) return { 'name': exception.filename, 'message': exception.message, 'source_lines': lines[top:bottom], 'line': lineno, 'before': '', 'during': during, 'after': '', 'total': total, 'top': top, 'bottom': bottom, } django/template/base.py +19 −5 Original line number Diff line number Diff line Loading @@ -135,13 +135,27 @@ class TemplateSyntaxError(Exception): class TemplateDoesNotExist(Exception): """ This exception is used when template loaders are unable to find a template. The tried argument is an optional list of tuples containing (origin, status), where origin is an Origin object and status is a string with the reason the template wasn't found. The exception used by backends when a template does not exist. Accepts the following optional arguments: backend The template backend class used when raising this exception. tried A list of sources that were tried when finding the template. This is formatted as a list of tuples containing (origin, status), where origin is an Origin object and status is a string with the reason the template wasn't found. chain A list of intermediate TemplateDoesNotExist exceptions. This is used to encapsulate multiple exceptions when loading templates from multiple engines. """ def __init__(self, msg, tried=None): def __init__(self, msg, tried=None, backend=None, chain=None): self.backend = backend self.tried = tried or [] self.chain = chain or [] super(TemplateDoesNotExist, self).__init__(msg) Loading django/template/loader.py +9 −9 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ def get_template(template_name, dirs=_dirs_undefined, using=None): Raises TemplateDoesNotExist if no such template exists. """ tried = [] chain = [] engines = _engine_list(using) for engine in engines: try: Loading @@ -33,9 +33,9 @@ def get_template(template_name, dirs=_dirs_undefined, using=None): else: return engine.get_template(template_name) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) raise TemplateDoesNotExist(template_name, tried=tried) raise TemplateDoesNotExist(template_name, chain=chain) def select_template(template_name_list, dirs=_dirs_undefined, using=None): Loading @@ -46,7 +46,7 @@ def select_template(template_name_list, dirs=_dirs_undefined, using=None): Raises TemplateDoesNotExist if no such template exists. """ tried = [] chain = [] engines = _engine_list(using) for template_name in template_name_list: for engine in engines: Loading @@ -63,10 +63,10 @@ def select_template(template_name_list, dirs=_dirs_undefined, using=None): else: return engine.get_template(template_name) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) if template_name_list: raise TemplateDoesNotExist(', '.join(template_name_list), tried=tried) raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain) else: raise TemplateDoesNotExist("No template names provided") Loading @@ -92,7 +92,7 @@ def render_to_string(template_name, context=None, return template.render(context, request) else: tried = [] chain = [] # Some deprecated arguments were passed - use the legacy code path for engine in _engine_list(using): try: Loading Loading @@ -124,13 +124,13 @@ def render_to_string(template_name, context=None, "method doesn't support the dictionary argument." % engine.name, stacklevel=2) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) continue if template_name: if isinstance(template_name, (list, tuple)): template_name = ', '.join(template_name) raise TemplateDoesNotExist(template_name, tried=tried) raise TemplateDoesNotExist(template_name, chain=chain) else: raise TemplateDoesNotExist("No template names provided") Loading Loading
django/template/backends/django.py +24 −6 Original line number Diff line number Diff line # Since this package contains a "django" module, this is required on Python 2. from __future__ import absolute_import import sys import warnings from django.conf import settings from django.template import TemplateDoesNotExist from django.template.context import Context, RequestContext, make_context from django.template.engine import Engine, _dirs_undefined from django.utils import six from django.utils.deprecation import RemovedInDjango20Warning from .base import BaseEngine Loading @@ -24,21 +27,23 @@ class DjangoTemplates(BaseEngine): self.engine = Engine(self.dirs, self.app_dirs, **options) def from_string(self, template_code): return Template(self.engine.from_string(template_code)) return Template(self.engine.from_string(template_code), self) def get_template(self, template_name, dirs=_dirs_undefined): return Template(self.engine.get_template(template_name, dirs)) try: return Template(self.engine.get_template(template_name, dirs), self) except TemplateDoesNotExist as exc: reraise(exc, self) class Template(object): def __init__(self, template): def __init__(self, template, backend): self.template = template self.backend = backend @property def origin(self): # TODO: define the Origin API. For now simply forwarding to the # underlying Template preserves backwards-compatibility. return self.template.origin def render(self, context=None, request=None): Loading Loading @@ -71,4 +76,17 @@ class Template(object): else: context = make_context(context, request) try: return self.template.render(context) except TemplateDoesNotExist as exc: reraise(exc, self.backend) def reraise(exc, backend): """ Reraise TemplateDoesNotExist while maintaining template debug information. """ new = exc.__class__(*exc.args, tried=exc.tried, backend=backend) if hasattr(exc, 'template_debug'): new.template_debug = exc.template_debug six.reraise(exc.__class__, new, sys.exc_info()[2])
django/template/backends/dummy.py +12 −4 Original line number Diff line number Diff line # Since this package contains a "django" module, this is required on Python 2. from __future__ import absolute_import import errno import io import string from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.template import TemplateDoesNotExist from django.template import Origin, TemplateDoesNotExist from django.utils.html import conditional_escape from .base import BaseEngine Loading @@ -29,17 +30,24 @@ class TemplateStrings(BaseEngine): return Template(template_code) def get_template(self, template_name): tried = [] for template_file in self.iter_template_filenames(template_name): try: with io.open(template_file, encoding=settings.FILE_CHARSET) as fp: template_code = fp.read() except IOError: except IOError as e: if e.errno == errno.ENOENT: tried.append(( Origin(template_file, template_name, self), 'Source does not exist', )) continue raise return Template(template_code) else: raise TemplateDoesNotExist(template_name) raise TemplateDoesNotExist(template_name, tried=tried, backend=self) class Template(string.Template): Loading
django/template/backends/jinja2.py +48 −4 Original line number Diff line number Diff line Loading @@ -41,17 +41,24 @@ class Jinja2(BaseEngine): try: return Template(self.env.get_template(template_name)) except jinja2.TemplateNotFound as exc: six.reraise(TemplateDoesNotExist, TemplateDoesNotExist(exc.args), sys.exc_info()[2]) six.reraise( TemplateDoesNotExist, TemplateDoesNotExist(exc.name, backend=self), sys.exc_info()[2], ) except jinja2.TemplateSyntaxError as exc: six.reraise(TemplateSyntaxError, TemplateSyntaxError(exc.args), sys.exc_info()[2]) new = TemplateSyntaxError(exc.args) new.template_debug = get_exception_info(exc) six.reraise(TemplateSyntaxError, new, sys.exc_info()[2]) class Template(object): def __init__(self, template): self.template = template self.origin = Origin( name=template.filename, template_name=template.name, ) def render(self, context=None, request=None): if context is None: Loading @@ -61,3 +68,40 @@ class Template(object): context['csrf_input'] = csrf_input_lazy(request) context['csrf_token'] = csrf_token_lazy(request) return self.template.render(context) class Origin(object): """ A container to hold debug information as described in the template API documentation. """ def __init__(self, name, template_name): self.name = name self.template_name = template_name def get_exception_info(exception): """ Formats exception information for display on the debug page using the structure described in the template API documentation. """ context_lines = 10 lineno = exception.lineno lines = list(enumerate(exception.source.strip().split("\n"), start=1)) during = lines[lineno - 1][1] total = len(lines) top = max(0, lineno - context_lines - 1) bottom = min(total, lineno + context_lines) return { 'name': exception.filename, 'message': exception.message, 'source_lines': lines[top:bottom], 'line': lineno, 'before': '', 'during': during, 'after': '', 'total': total, 'top': top, 'bottom': bottom, }
django/template/base.py +19 −5 Original line number Diff line number Diff line Loading @@ -135,13 +135,27 @@ class TemplateSyntaxError(Exception): class TemplateDoesNotExist(Exception): """ This exception is used when template loaders are unable to find a template. The tried argument is an optional list of tuples containing (origin, status), where origin is an Origin object and status is a string with the reason the template wasn't found. The exception used by backends when a template does not exist. Accepts the following optional arguments: backend The template backend class used when raising this exception. tried A list of sources that were tried when finding the template. This is formatted as a list of tuples containing (origin, status), where origin is an Origin object and status is a string with the reason the template wasn't found. chain A list of intermediate TemplateDoesNotExist exceptions. This is used to encapsulate multiple exceptions when loading templates from multiple engines. """ def __init__(self, msg, tried=None): def __init__(self, msg, tried=None, backend=None, chain=None): self.backend = backend self.tried = tried or [] self.chain = chain or [] super(TemplateDoesNotExist, self).__init__(msg) Loading
django/template/loader.py +9 −9 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ def get_template(template_name, dirs=_dirs_undefined, using=None): Raises TemplateDoesNotExist if no such template exists. """ tried = [] chain = [] engines = _engine_list(using) for engine in engines: try: Loading @@ -33,9 +33,9 @@ def get_template(template_name, dirs=_dirs_undefined, using=None): else: return engine.get_template(template_name) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) raise TemplateDoesNotExist(template_name, tried=tried) raise TemplateDoesNotExist(template_name, chain=chain) def select_template(template_name_list, dirs=_dirs_undefined, using=None): Loading @@ -46,7 +46,7 @@ def select_template(template_name_list, dirs=_dirs_undefined, using=None): Raises TemplateDoesNotExist if no such template exists. """ tried = [] chain = [] engines = _engine_list(using) for template_name in template_name_list: for engine in engines: Loading @@ -63,10 +63,10 @@ def select_template(template_name_list, dirs=_dirs_undefined, using=None): else: return engine.get_template(template_name) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) if template_name_list: raise TemplateDoesNotExist(', '.join(template_name_list), tried=tried) raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain) else: raise TemplateDoesNotExist("No template names provided") Loading @@ -92,7 +92,7 @@ def render_to_string(template_name, context=None, return template.render(context, request) else: tried = [] chain = [] # Some deprecated arguments were passed - use the legacy code path for engine in _engine_list(using): try: Loading Loading @@ -124,13 +124,13 @@ def render_to_string(template_name, context=None, "method doesn't support the dictionary argument." % engine.name, stacklevel=2) except TemplateDoesNotExist as e: tried.extend(e.tried) chain.append(e) continue if template_name: if isinstance(template_name, (list, tuple)): template_name = ', '.join(template_name) raise TemplateDoesNotExist(template_name, tried=tried) raise TemplateDoesNotExist(template_name, chain=chain) else: raise TemplateDoesNotExist("No template names provided") Loading