debug.py 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from django.template.base import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError
  2. from django.utils.encoding import force_unicode
  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 aslocaltime
  7. class DebugLexer(Lexer):
  8. def __init__(self, template_string, origin):
  9. super(DebugLexer, self).__init__(template_string, origin)
  10. def tokenize(self):
  11. "Return a list of tokens from a given template_string"
  12. result, upto = [], 0
  13. for match in tag_re.finditer(self.template_string):
  14. start, end = match.span()
  15. if start > upto:
  16. result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
  17. upto = start
  18. result.append(self.create_token(self.template_string[start:end], (start, end), True))
  19. upto = end
  20. last_bit = self.template_string[upto:]
  21. if last_bit:
  22. result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
  23. return result
  24. def create_token(self, token_string, source, in_tag):
  25. token = super(DebugLexer, self).create_token(token_string, in_tag)
  26. token.source = self.origin, source
  27. return token
  28. class DebugParser(Parser):
  29. def __init__(self, lexer):
  30. super(DebugParser, self).__init__(lexer)
  31. self.command_stack = []
  32. def enter_command(self, command, token):
  33. self.command_stack.append( (command, token.source) )
  34. def exit_command(self):
  35. self.command_stack.pop()
  36. def error(self, token, msg):
  37. return self.source_error(token.source, msg)
  38. def source_error(self, source, msg):
  39. e = TemplateSyntaxError(msg)
  40. e.django_template_source = source
  41. return e
  42. def create_nodelist(self):
  43. return DebugNodeList()
  44. def create_variable_node(self, contents):
  45. return DebugVariableNode(contents)
  46. def extend_nodelist(self, nodelist, node, token):
  47. node.source = token.source
  48. super(DebugParser, self).extend_nodelist(nodelist, node, token)
  49. def unclosed_block_tag(self, parse_until):
  50. command, source = self.command_stack.pop()
  51. msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
  52. raise self.source_error(source, msg)
  53. def compile_function_error(self, token, e):
  54. if not hasattr(e, 'django_template_source'):
  55. e.django_template_source = token.source
  56. class DebugNodeList(NodeList):
  57. def render_node(self, node, context):
  58. try:
  59. return node.render(context)
  60. except Exception, e:
  61. if not hasattr(e, 'django_template_source'):
  62. e.django_template_source = node.source
  63. raise
  64. class DebugVariableNode(VariableNode):
  65. def render(self, context):
  66. try:
  67. output = self.filter_expression.resolve(context)
  68. output = aslocaltime(output, use_tz=context.use_tz)
  69. output = localize(output, use_l10n=context.use_l10n)
  70. output = force_unicode(output)
  71. except UnicodeDecodeError:
  72. return ''
  73. except Exception, e:
  74. if not hasattr(e, 'django_template_source'):
  75. e.django_template_source = self.source
  76. raise
  77. if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData):
  78. return escape(output)
  79. else:
  80. return output