1 from django
.template
.base
import Lexer
, Parser
, tag_re
, NodeList
, VariableNode
, TemplateSyntaxError
2 from django
.utils
.encoding
import force_text
3 from django
.utils
.html
import escape
4 from django
.utils
.safestring
import SafeData
, EscapeData
5 from django
.utils
.formats
import localize
6 from django
.utils
.timezone
import template_localtime
9 class DebugLexer(Lexer
):
10 def __init__(self
, template_string
, origin
):
11 super(DebugLexer
, self
).__init
__(template_string
, origin
)
14 "Return a list of tokens from a given template_string"
16 for match
in tag_re
.finditer(self
.template_string
):
17 start
, end
= match
.span()
19 result
.append(self
.create_token(self
.template_string
[upto
:start
], (upto
, start
), False))
21 result
.append(self
.create_token(self
.template_string
[start
:end
], (start
, end
), True))
23 last_bit
= self
.template_string
[upto
:]
25 result
.append(self
.create_token(last_bit
, (upto
, upto
+ len(last_bit
)), False))
28 def create_token(self
, token_string
, source
, in_tag
):
29 token
= super(DebugLexer
, self
).create_token(token_string
, in_tag
)
30 token
.source
= self
.origin
, source
33 class DebugParser(Parser
):
34 def __init__(self
, lexer
):
35 super(DebugParser
, self
).__init
__(lexer
)
36 self
.command_stack
= []
38 def enter_command(self
, command
, token
):
39 self
.command_stack
.append( (command
, token
.source
) )
41 def exit_command(self
):
42 self
.command_stack
.pop()
44 def error(self
, token
, msg
):
45 return self
.source_error(token
.source
, msg
)
47 def source_error(self
, source
, msg
):
48 e
= TemplateSyntaxError(msg
)
49 e
.django_template_source
= source
52 def create_nodelist(self
):
53 return DebugNodeList()
55 def create_variable_node(self
, contents
):
56 return DebugVariableNode(contents
)
58 def extend_nodelist(self
, nodelist
, node
, token
):
59 node
.source
= token
.source
60 super(DebugParser
, self
).extend_nodelist(nodelist
, node
, token
)
62 def unclosed_block_tag(self
, parse_until
):
63 command
, source
= self
.command_stack
.pop()
64 msg
= "Unclosed tag '%s'. Looking for one of: %s " % (command
, ', '.join(parse_until
))
65 raise self
.source_error(source
, msg
)
67 def compile_function_error(self
, token
, e
):
68 if not hasattr(e
, 'django_template_source'):
69 e
.django_template_source
= token
.source
71 class DebugNodeList(NodeList
):
72 def render_node(self
, node
, context
):
74 return node
.render(context
)
75 except Exception as e
:
76 if not hasattr(e
, 'django_template_source'):
77 e
.django_template_source
= node
.source
81 class DebugVariableNode(VariableNode
):
82 def render(self
, context
):
84 output
= self
.filter_expression
.resolve(context
)
85 output
= template_localtime(output
, use_tz
=context
.use_tz
)
86 output
= localize(output
, use_l10n
=context
.use_l10n
)
87 output
= force_text(output
)
88 except UnicodeDecodeError:
90 except Exception as e
:
91 if not hasattr(e
, 'django_template_source'):
92 e
.django_template_source
= self
.source
94 if (context
.autoescape
and not isinstance(output
, SafeData
)) or isinstance(output
, EscapeData
):