PageRenderTime 56ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/python/lib/Lib/site-packages/django/template/base.py

http://github.com/JetBrains/intellij-community
Python | 1019 lines | 973 code | 29 blank | 17 comment | 27 complexity | 5366b7941915f04b72078dc3354d5de5 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, MPL-2.0-no-copyleft-exception, MIT, EPL-1.0, AGPL-1.0
  1. import imp
  2. import re
  3. from inspect import getargspec
  4. from django.conf import settings
  5. from django.template.context import Context, RequestContext, ContextPopException
  6. from django.utils.importlib import import_module
  7. from django.utils.itercompat import is_iterable
  8. from django.utils.functional import curry, Promise
  9. from django.utils.text import smart_split, unescape_string_literal, get_text_list
  10. from django.utils.encoding import smart_unicode, force_unicode, smart_str
  11. from django.utils.translation import ugettext as _
  12. from django.utils.safestring import SafeData, EscapeData, mark_safe, mark_for_escaping
  13. from django.utils.formats import localize
  14. from django.utils.html import escape
  15. from django.utils.module_loading import module_has_submodule
  16. TOKEN_TEXT = 0
  17. TOKEN_VAR = 1
  18. TOKEN_BLOCK = 2
  19. TOKEN_COMMENT = 3
  20. # template syntax constants
  21. FILTER_SEPARATOR = '|'
  22. FILTER_ARGUMENT_SEPARATOR = ':'
  23. VARIABLE_ATTRIBUTE_SEPARATOR = '.'
  24. BLOCK_TAG_START = '{%'
  25. BLOCK_TAG_END = '%}'
  26. VARIABLE_TAG_START = '{{'
  27. VARIABLE_TAG_END = '}}'
  28. COMMENT_TAG_START = '{#'
  29. COMMENT_TAG_END = '#}'
  30. TRANSLATOR_COMMENT_MARK = 'Translators'
  31. SINGLE_BRACE_START = '{'
  32. SINGLE_BRACE_END = '}'
  33. ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.'
  34. # what to report as the origin for templates that come from non-loader sources
  35. # (e.g. strings)
  36. UNKNOWN_SOURCE = '<unknown source>'
  37. # match a variable or block tag and capture the entire tag, including start/end delimiters
  38. tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
  39. re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
  40. re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
  41. # global dictionary of libraries that have been loaded using get_library
  42. libraries = {}
  43. # global list of libraries to load by default for a new parser
  44. builtins = []
  45. # True if TEMPLATE_STRING_IF_INVALID contains a format string (%s). None means
  46. # uninitialised.
  47. invalid_var_format_string = None
  48. class TemplateSyntaxError(Exception):
  49. pass
  50. class TemplateDoesNotExist(Exception):
  51. pass
  52. class TemplateEncodingError(Exception):
  53. pass
  54. class VariableDoesNotExist(Exception):
  55. def __init__(self, msg, params=()):
  56. self.msg = msg
  57. self.params = params
  58. def __str__(self):
  59. return unicode(self).encode('utf-8')
  60. def __unicode__(self):
  61. return self.msg % tuple([force_unicode(p, errors='replace') for p in self.params])
  62. class InvalidTemplateLibrary(Exception):
  63. pass
  64. class Origin(object):
  65. def __init__(self, name):
  66. self.name = name
  67. def reload(self):
  68. raise NotImplementedError
  69. def __str__(self):
  70. return self.name
  71. class StringOrigin(Origin):
  72. def __init__(self, source):
  73. super(StringOrigin, self).__init__(UNKNOWN_SOURCE)
  74. self.source = source
  75. def reload(self):
  76. return self.source
  77. class Template(object):
  78. def __init__(self, template_string, origin=None, name='<Unknown Template>'):
  79. try:
  80. template_string = smart_unicode(template_string)
  81. except UnicodeDecodeError:
  82. raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.")
  83. if settings.TEMPLATE_DEBUG and origin is None:
  84. origin = StringOrigin(template_string)
  85. self.nodelist = compile_string(template_string, origin)
  86. self.name = name
  87. def __iter__(self):
  88. for node in self.nodelist:
  89. for subnode in node:
  90. yield subnode
  91. def _render(self, context):
  92. return self.nodelist.render(context)
  93. def render(self, context):
  94. "Display stage -- can be called many times"
  95. context.render_context.push()
  96. try:
  97. return self._render(context)
  98. finally:
  99. context.render_context.pop()
  100. def compile_string(template_string, origin):
  101. "Compiles template_string into NodeList ready for rendering"
  102. if settings.TEMPLATE_DEBUG:
  103. from debug import DebugLexer, DebugParser
  104. lexer_class, parser_class = DebugLexer, DebugParser
  105. else:
  106. lexer_class, parser_class = Lexer, Parser
  107. lexer = lexer_class(template_string, origin)
  108. parser = parser_class(lexer.tokenize())
  109. return parser.parse()
  110. class Token(object):
  111. def __init__(self, token_type, contents):
  112. # token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT.
  113. self.token_type, self.contents = token_type, contents
  114. self.lineno = None
  115. def __str__(self):
  116. return '<%s token: "%s...">' % \
  117. ({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type],
  118. self.contents[:20].replace('\n', ''))
  119. def split_contents(self):
  120. split = []
  121. bits = iter(smart_split(self.contents))
  122. for bit in bits:
  123. # Handle translation-marked template pieces
  124. if bit.startswith('_("') or bit.startswith("_('"):
  125. sentinal = bit[2] + ')'
  126. trans_bit = [bit]
  127. while not bit.endswith(sentinal):
  128. bit = bits.next()
  129. trans_bit.append(bit)
  130. bit = ' '.join(trans_bit)
  131. split.append(bit)
  132. return split
  133. class Lexer(object):
  134. def __init__(self, template_string, origin):
  135. self.template_string = template_string
  136. self.origin = origin
  137. self.lineno = 1
  138. def tokenize(self):
  139. "Return a list of tokens from a given template_string."
  140. in_tag = False
  141. result = []
  142. for bit in tag_re.split(self.template_string):
  143. if bit:
  144. result.append(self.create_token(bit, in_tag))
  145. in_tag = not in_tag
  146. return result
  147. def create_token(self, token_string, in_tag):
  148. """
  149. Convert the given token string into a new Token object and return it.
  150. If in_tag is True, we are processing something that matched a tag,
  151. otherwise it should be treated as a literal string.
  152. """
  153. if in_tag:
  154. if token_string.startswith(VARIABLE_TAG_START):
  155. token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip())
  156. elif token_string.startswith(BLOCK_TAG_START):
  157. token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
  158. elif token_string.startswith(COMMENT_TAG_START):
  159. content = ''
  160. if token_string.find(TRANSLATOR_COMMENT_MARK):
  161. content = token_string[len(COMMENT_TAG_START):-len(COMMENT_TAG_END)].strip()
  162. token = Token(TOKEN_COMMENT, content)
  163. else:
  164. token = Token(TOKEN_TEXT, token_string)
  165. token.lineno = self.lineno
  166. self.lineno += token_string.count('\n')
  167. return token
  168. class Parser(object):
  169. def __init__(self, tokens):
  170. self.tokens = tokens
  171. self.tags = {}
  172. self.filters = {}
  173. for lib in builtins:
  174. self.add_library(lib)
  175. def parse(self, parse_until=None):
  176. if parse_until is None: parse_until = []
  177. nodelist = self.create_nodelist()
  178. while self.tokens:
  179. token = self.next_token()
  180. if token.token_type == TOKEN_TEXT:
  181. self.extend_nodelist(nodelist, TextNode(token.contents), token)
  182. elif token.token_type == TOKEN_VAR:
  183. if not token.contents:
  184. self.empty_variable(token)
  185. filter_expression = self.compile_filter(token.contents)
  186. var_node = self.create_variable_node(filter_expression)
  187. self.extend_nodelist(nodelist, var_node,token)
  188. elif token.token_type == TOKEN_BLOCK:
  189. if token.contents in parse_until:
  190. # put token back on token list so calling code knows why it terminated
  191. self.prepend_token(token)
  192. return nodelist
  193. try:
  194. command = token.contents.split()[0]
  195. except IndexError:
  196. self.empty_block_tag(token)
  197. # execute callback function for this tag and append resulting node
  198. self.enter_command(command, token)
  199. try:
  200. compile_func = self.tags[command]
  201. except KeyError:
  202. self.invalid_block_tag(token, command, parse_until)
  203. try:
  204. compiled_result = compile_func(self, token)
  205. except TemplateSyntaxError, e:
  206. if not self.compile_function_error(token, e):
  207. raise
  208. self.extend_nodelist(nodelist, compiled_result, token)
  209. self.exit_command()
  210. if parse_until:
  211. self.unclosed_block_tag(parse_until)
  212. return nodelist
  213. def skip_past(self, endtag):
  214. while self.tokens:
  215. token = self.next_token()
  216. if token.token_type == TOKEN_BLOCK and token.contents == endtag:
  217. return
  218. self.unclosed_block_tag([endtag])
  219. def create_variable_node(self, filter_expression):
  220. return VariableNode(filter_expression)
  221. def create_nodelist(self):
  222. return NodeList()
  223. def extend_nodelist(self, nodelist, node, token):
  224. if node.must_be_first and nodelist:
  225. try:
  226. if nodelist.contains_nontext:
  227. raise AttributeError
  228. except AttributeError:
  229. raise TemplateSyntaxError("%r must be the first tag in the template." % node)
  230. if isinstance(nodelist, NodeList) and not isinstance(node, TextNode):
  231. nodelist.contains_nontext = True
  232. nodelist.append(node)
  233. def enter_command(self, command, token):
  234. pass
  235. def exit_command(self):
  236. pass
  237. def error(self, token, msg):
  238. return TemplateSyntaxError(msg)
  239. def empty_variable(self, token):
  240. raise self.error(token, "Empty variable tag")
  241. def empty_block_tag(self, token):
  242. raise self.error(token, "Empty block tag")
  243. def invalid_block_tag(self, token, command, parse_until=None):
  244. if parse_until:
  245. raise self.error(token, "Invalid block tag: '%s', expected %s" % (command, get_text_list(["'%s'" % p for p in parse_until])))
  246. raise self.error(token, "Invalid block tag: '%s'" % command)
  247. def unclosed_block_tag(self, parse_until):
  248. raise self.error(None, "Unclosed tags: %s " % ', '.join(parse_until))
  249. def compile_function_error(self, token, e):
  250. pass
  251. def next_token(self):
  252. return self.tokens.pop(0)
  253. def prepend_token(self, token):
  254. self.tokens.insert(0, token)
  255. def delete_first_token(self):
  256. del self.tokens[0]
  257. def add_library(self, lib):
  258. self.tags.update(lib.tags)
  259. self.filters.update(lib.filters)
  260. def compile_filter(self, token):
  261. "Convenient wrapper for FilterExpression"
  262. return FilterExpression(token, self)
  263. def find_filter(self, filter_name):
  264. if filter_name in self.filters:
  265. return self.filters[filter_name]
  266. else:
  267. raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
  268. class TokenParser(object):
  269. """
  270. Subclass this and implement the top() method to parse a template line. When
  271. instantiating the parser, pass in the line from the Django template parser.
  272. The parser's "tagname" instance-variable stores the name of the tag that
  273. the filter was called with.
  274. """
  275. def __init__(self, subject):
  276. self.subject = subject
  277. self.pointer = 0
  278. self.backout = []
  279. self.tagname = self.tag()
  280. def top(self):
  281. "Overload this method to do the actual parsing and return the result."
  282. raise NotImplementedError()
  283. def more(self):
  284. "Returns True if there is more stuff in the tag."
  285. return self.pointer < len(self.subject)
  286. def back(self):
  287. "Undoes the last microparser. Use this for lookahead and backtracking."
  288. if not len(self.backout):
  289. raise TemplateSyntaxError("back called without some previous parsing")
  290. self.pointer = self.backout.pop()
  291. def tag(self):
  292. "A microparser that just returns the next tag from the line."
  293. subject = self.subject
  294. i = self.pointer
  295. if i >= len(subject):
  296. raise TemplateSyntaxError("expected another tag, found end of string: %s" % subject)
  297. p = i
  298. while i < len(subject) and subject[i] not in (' ', '\t'):
  299. i += 1
  300. s = subject[p:i]
  301. while i < len(subject) and subject[i] in (' ', '\t'):
  302. i += 1
  303. self.backout.append(self.pointer)
  304. self.pointer = i
  305. return s
  306. def value(self):
  307. "A microparser that parses for a value: some string constant or variable name."
  308. subject = self.subject
  309. i = self.pointer
  310. def next_space_index(subject, i):
  311. "Increment pointer until a real space (i.e. a space not within quotes) is encountered"
  312. while i < len(subject) and subject[i] not in (' ', '\t'):
  313. if subject[i] in ('"', "'"):
  314. c = subject[i]
  315. i += 1
  316. while i < len(subject) and subject[i] != c:
  317. i += 1
  318. if i >= len(subject):
  319. raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
  320. i += 1
  321. return i
  322. if i >= len(subject):
  323. raise TemplateSyntaxError("Searching for value. Expected another value but found end of string: %s" % subject)
  324. if subject[i] in ('"', "'"):
  325. p = i
  326. i += 1
  327. while i < len(subject) and subject[i] != subject[p]:
  328. i += 1
  329. if i >= len(subject):
  330. raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
  331. i += 1
  332. # Continue parsing until next "real" space, so that filters are also included
  333. i = next_space_index(subject, i)
  334. res = subject[p:i]
  335. while i < len(subject) and subject[i] in (' ', '\t'):
  336. i += 1
  337. self.backout.append(self.pointer)
  338. self.pointer = i
  339. return res
  340. else:
  341. p = i
  342. i = next_space_index(subject, i)
  343. s = subject[p:i]
  344. while i < len(subject) and subject[i] in (' ', '\t'):
  345. i += 1
  346. self.backout.append(self.pointer)
  347. self.pointer = i
  348. return s
  349. # This only matches constant *strings* (things in quotes or marked for
  350. # translation). Numbers are treated as variables for implementation reasons
  351. # (so that they retain their type when passed to filters).
  352. constant_string = r"""
  353. (?:%(i18n_open)s%(strdq)s%(i18n_close)s|
  354. %(i18n_open)s%(strsq)s%(i18n_close)s|
  355. %(strdq)s|
  356. %(strsq)s)
  357. """ % {
  358. 'strdq': r'"[^"\\]*(?:\\.[^"\\]*)*"', # double-quoted string
  359. 'strsq': r"'[^'\\]*(?:\\.[^'\\]*)*'", # single-quoted string
  360. 'i18n_open' : re.escape("_("),
  361. 'i18n_close' : re.escape(")"),
  362. }
  363. constant_string = constant_string.replace("\n", "")
  364. filter_raw_string = r"""
  365. ^(?P<constant>%(constant)s)|
  366. ^(?P<var>[%(var_chars)s]+|%(num)s)|
  367. (?:%(filter_sep)s
  368. (?P<filter_name>\w+)
  369. (?:%(arg_sep)s
  370. (?:
  371. (?P<constant_arg>%(constant)s)|
  372. (?P<var_arg>[%(var_chars)s]+|%(num)s)
  373. )
  374. )?
  375. )""" % {
  376. 'constant': constant_string,
  377. 'num': r'[-+\.]?\d[\d\.e]*',
  378. 'var_chars': "\w\." ,
  379. 'filter_sep': re.escape(FILTER_SEPARATOR),
  380. 'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR),
  381. }
  382. filter_re = re.compile(filter_raw_string, re.UNICODE|re.VERBOSE)
  383. class FilterExpression(object):
  384. r"""
  385. Parses a variable token and its optional filters (all as a single string),
  386. and return a list of tuples of the filter name and arguments.
  387. Sample:
  388. >>> token = 'variable|default:"Default value"|date:"Y-m-d"'
  389. >>> p = Parser('')
  390. >>> fe = FilterExpression(token, p)
  391. >>> len(fe.filters)
  392. 2
  393. >>> fe.var
  394. <Variable: 'variable'>
  395. This class should never be instantiated outside of the
  396. get_filters_from_token helper function.
  397. """
  398. def __init__(self, token, parser):
  399. self.token = token
  400. matches = filter_re.finditer(token)
  401. var_obj = None
  402. filters = []
  403. upto = 0
  404. for match in matches:
  405. start = match.start()
  406. if upto != start:
  407. raise TemplateSyntaxError("Could not parse some characters: %s|%s|%s" % \
  408. (token[:upto], token[upto:start], token[start:]))
  409. if var_obj is None:
  410. var, constant = match.group("var", "constant")
  411. if constant:
  412. try:
  413. var_obj = Variable(constant).resolve({})
  414. except VariableDoesNotExist:
  415. var_obj = None
  416. elif var is None:
  417. raise TemplateSyntaxError("Could not find variable at start of %s." % token)
  418. else:
  419. var_obj = Variable(var)
  420. else:
  421. filter_name = match.group("filter_name")
  422. args = []
  423. constant_arg, var_arg = match.group("constant_arg", "var_arg")
  424. if constant_arg:
  425. args.append((False, Variable(constant_arg).resolve({})))
  426. elif var_arg:
  427. args.append((True, Variable(var_arg)))
  428. filter_func = parser.find_filter(filter_name)
  429. self.args_check(filter_name, filter_func, args)
  430. filters.append((filter_func, args))
  431. upto = match.end()
  432. if upto != len(token):
  433. raise TemplateSyntaxError("Could not parse the remainder: '%s' from '%s'" % (token[upto:], token))
  434. self.filters = filters
  435. self.var = var_obj
  436. def resolve(self, context, ignore_failures=False):
  437. if isinstance(self.var, Variable):
  438. try:
  439. obj = self.var.resolve(context)
  440. except VariableDoesNotExist:
  441. if ignore_failures:
  442. obj = None
  443. else:
  444. if settings.TEMPLATE_STRING_IF_INVALID:
  445. global invalid_var_format_string
  446. if invalid_var_format_string is None:
  447. invalid_var_format_string = '%s' in settings.TEMPLATE_STRING_IF_INVALID
  448. if invalid_var_format_string:
  449. return settings.TEMPLATE_STRING_IF_INVALID % self.var
  450. return settings.TEMPLATE_STRING_IF_INVALID
  451. else:
  452. obj = settings.TEMPLATE_STRING_IF_INVALID
  453. else:
  454. obj = self.var
  455. for func, args in self.filters:
  456. arg_vals = []
  457. for lookup, arg in args:
  458. if not lookup:
  459. arg_vals.append(mark_safe(arg))
  460. else:
  461. arg_vals.append(arg.resolve(context))
  462. if getattr(func, 'needs_autoescape', False):
  463. new_obj = func(obj, autoescape=context.autoescape, *arg_vals)
  464. else:
  465. new_obj = func(obj, *arg_vals)
  466. if getattr(func, 'is_safe', False) and isinstance(obj, SafeData):
  467. obj = mark_safe(new_obj)
  468. elif isinstance(obj, EscapeData):
  469. obj = mark_for_escaping(new_obj)
  470. else:
  471. obj = new_obj
  472. return obj
  473. def args_check(name, func, provided):
  474. provided = list(provided)
  475. plen = len(provided)
  476. # Check to see if a decorator is providing the real function.
  477. func = getattr(func, '_decorated_function', func)
  478. args, varargs, varkw, defaults = getargspec(func)
  479. # First argument is filter input.
  480. args.pop(0)
  481. if defaults:
  482. nondefs = args[:-len(defaults)]
  483. else:
  484. nondefs = args
  485. # Args without defaults must be provided.
  486. try:
  487. for arg in nondefs:
  488. provided.pop(0)
  489. except IndexError:
  490. # Not enough
  491. raise TemplateSyntaxError("%s requires %d arguments, %d provided" % (name, len(nondefs), plen))
  492. # Defaults can be overridden.
  493. defaults = defaults and list(defaults) or []
  494. try:
  495. for parg in provided:
  496. defaults.pop(0)
  497. except IndexError:
  498. # Too many.
  499. raise TemplateSyntaxError("%s requires %d arguments, %d provided" % (name, len(nondefs), plen))
  500. return True
  501. args_check = staticmethod(args_check)
  502. def __str__(self):
  503. return self.token
  504. def resolve_variable(path, context):
  505. """
  506. Returns the resolved variable, which may contain attribute syntax, within
  507. the given context.
  508. Deprecated; use the Variable class instead.
  509. """
  510. return Variable(path).resolve(context)
  511. class Variable(object):
  512. r"""
  513. A template variable, resolvable against a given context. The variable may be
  514. a hard-coded string (if it begins and ends with single or double quote
  515. marks)::
  516. >>> c = {'article': {'section':u'News'}}
  517. >>> Variable('article.section').resolve(c)
  518. u'News'
  519. >>> Variable('article').resolve(c)
  520. {'section': u'News'}
  521. >>> class AClass: pass
  522. >>> c = AClass()
  523. >>> c.article = AClass()
  524. >>> c.article.section = u'News'
  525. (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
  526. """
  527. def __init__(self, var):
  528. self.var = var
  529. self.literal = None
  530. self.lookups = None
  531. self.translate = False
  532. try:
  533. # First try to treat this variable as a number.
  534. #
  535. # Note that this could cause an OverflowError here that we're not
  536. # catching. Since this should only happen at compile time, that's
  537. # probably OK.
  538. self.literal = float(var)
  539. # So it's a float... is it an int? If the original value contained a
  540. # dot or an "e" then it was a float, not an int.
  541. if '.' not in var and 'e' not in var.lower():
  542. self.literal = int(self.literal)
  543. # "2." is invalid
  544. if var.endswith('.'):
  545. raise ValueError
  546. except ValueError:
  547. # A ValueError means that the variable isn't a number.
  548. if var.startswith('_(') and var.endswith(')'):
  549. # The result of the lookup should be translated at rendering
  550. # time.
  551. self.translate = True
  552. var = var[2:-1]
  553. # If it's wrapped with quotes (single or double), then
  554. # we're also dealing with a literal.
  555. try:
  556. self.literal = mark_safe(unescape_string_literal(var))
  557. except ValueError:
  558. # Otherwise we'll set self.lookups so that resolve() knows we're
  559. # dealing with a bonafide variable
  560. if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_':
  561. raise TemplateSyntaxError("Variables and attributes may not begin with underscores: '%s'" % var)
  562. self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
  563. def resolve(self, context):
  564. """Resolve this variable against a given context."""
  565. if self.lookups is not None:
  566. # We're dealing with a variable that needs to be resolved
  567. value = self._resolve_lookup(context)
  568. else:
  569. # We're dealing with a literal, so it's already been "resolved"
  570. value = self.literal
  571. if self.translate:
  572. return _(value)
  573. return value
  574. def __repr__(self):
  575. return "<%s: %r>" % (self.__class__.__name__, self.var)
  576. def __str__(self):
  577. return self.var
  578. def _resolve_lookup(self, context):
  579. """
  580. Performs resolution of a real variable (i.e. not a literal) against the
  581. given context.
  582. As indicated by the method's name, this method is an implementation
  583. detail and shouldn't be called by external code. Use Variable.resolve()
  584. instead.
  585. """
  586. current = context
  587. try: # catch-all for silent variable failures
  588. for bit in self.lookups:
  589. try: # dictionary lookup
  590. current = current[bit]
  591. except (TypeError, AttributeError, KeyError):
  592. try: # attribute lookup
  593. current = getattr(current, bit)
  594. except (TypeError, AttributeError):
  595. try: # list-index lookup
  596. current = current[int(bit)]
  597. except (IndexError, # list index out of range
  598. ValueError, # invalid literal for int()
  599. KeyError, # current is a dict without `int(bit)` key
  600. TypeError, # unsubscriptable object
  601. ):
  602. raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute
  603. if callable(current):
  604. if getattr(current, 'alters_data', False):
  605. current = settings.TEMPLATE_STRING_IF_INVALID
  606. else:
  607. try: # method call (assuming no args required)
  608. current = current()
  609. except TypeError: # arguments *were* required
  610. # GOTCHA: This will also catch any TypeError
  611. # raised in the function itself.
  612. current = settings.TEMPLATE_STRING_IF_INVALID # invalid method call
  613. except Exception, e:
  614. if getattr(e, 'silent_variable_failure', False):
  615. current = settings.TEMPLATE_STRING_IF_INVALID
  616. else:
  617. raise
  618. return current
  619. class Node(object):
  620. # Set this to True for nodes that must be first in the template (although
  621. # they can be preceded by text nodes.
  622. must_be_first = False
  623. child_nodelists = ('nodelist',)
  624. def render(self, context):
  625. "Return the node rendered as a string"
  626. pass
  627. def __iter__(self):
  628. yield self
  629. def get_nodes_by_type(self, nodetype):
  630. "Return a list of all nodes (within this node and its nodelist) of the given type"
  631. nodes = []
  632. if isinstance(self, nodetype):
  633. nodes.append(self)
  634. for attr in self.child_nodelists:
  635. nodelist = getattr(self, attr, None)
  636. if nodelist:
  637. nodes.extend(nodelist.get_nodes_by_type(nodetype))
  638. return nodes
  639. class NodeList(list):
  640. # Set to True the first time a non-TextNode is inserted by
  641. # extend_nodelist().
  642. contains_nontext = False
  643. def render(self, context):
  644. bits = []
  645. for node in self:
  646. if isinstance(node, Node):
  647. bits.append(self.render_node(node, context))
  648. else:
  649. bits.append(node)
  650. return mark_safe(''.join([force_unicode(b) for b in bits]))
  651. def get_nodes_by_type(self, nodetype):
  652. "Return a list of all nodes of the given type"
  653. nodes = []
  654. for node in self:
  655. nodes.extend(node.get_nodes_by_type(nodetype))
  656. return nodes
  657. def render_node(self, node, context):
  658. return node.render(context)
  659. class TextNode(Node):
  660. def __init__(self, s):
  661. self.s = s
  662. def __repr__(self):
  663. return "<Text Node: '%s'>" % smart_str(self.s[:25], 'ascii',
  664. errors='replace')
  665. def render(self, context):
  666. return self.s
  667. def _render_value_in_context(value, context):
  668. """
  669. Converts any value to a string to become part of a rendered template. This
  670. means escaping, if required, and conversion to a unicode object. If value
  671. is a string, it is expected to have already been translated.
  672. """
  673. value = localize(value, use_l10n=context.use_l10n)
  674. value = force_unicode(value)
  675. if (context.autoescape and not isinstance(value, SafeData)) or isinstance(value, EscapeData):
  676. return escape(value)
  677. else:
  678. return value
  679. class VariableNode(Node):
  680. def __init__(self, filter_expression):
  681. self.filter_expression = filter_expression
  682. def __repr__(self):
  683. return "<Variable Node: %s>" % self.filter_expression
  684. def render(self, context):
  685. try:
  686. output = self.filter_expression.resolve(context)
  687. except UnicodeDecodeError:
  688. # Unicode conversion can fail sometimes for reasons out of our
  689. # control (e.g. exception rendering). In that case, we fail quietly.
  690. return ''
  691. return _render_value_in_context(output, context)
  692. def generic_tag_compiler(params, defaults, name, node_class, parser, token):
  693. "Returns a template.Node subclass."
  694. bits = token.split_contents()[1:]
  695. bmax = len(params)
  696. def_len = defaults and len(defaults) or 0
  697. bmin = bmax - def_len
  698. if(len(bits) < bmin or len(bits) > bmax):
  699. if bmin == bmax:
  700. message = "%s takes %s arguments" % (name, bmin)
  701. else:
  702. message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
  703. raise TemplateSyntaxError(message)
  704. return node_class(bits)
  705. class Library(object):
  706. def __init__(self):
  707. self.filters = {}
  708. self.tags = {}
  709. def tag(self, name=None, compile_function=None):
  710. if name == None and compile_function == None:
  711. # @register.tag()
  712. return self.tag_function
  713. elif name != None and compile_function == None:
  714. if(callable(name)):
  715. # @register.tag
  716. return self.tag_function(name)
  717. else:
  718. # @register.tag('somename') or @register.tag(name='somename')
  719. def dec(func):
  720. return self.tag(name, func)
  721. return dec
  722. elif name != None and compile_function != None:
  723. # register.tag('somename', somefunc)
  724. self.tags[name] = compile_function
  725. return compile_function
  726. else:
  727. raise InvalidTemplateLibrary("Unsupported arguments to Library.tag: (%r, %r)", (name, compile_function))
  728. def tag_function(self,func):
  729. self.tags[getattr(func, "_decorated_function", func).__name__] = func
  730. return func
  731. def filter(self, name=None, filter_func=None):
  732. if name == None and filter_func == None:
  733. # @register.filter()
  734. return self.filter_function
  735. elif filter_func == None:
  736. if(callable(name)):
  737. # @register.filter
  738. return self.filter_function(name)
  739. else:
  740. # @register.filter('somename') or @register.filter(name='somename')
  741. def dec(func):
  742. return self.filter(name, func)
  743. return dec
  744. elif name != None and filter_func != None:
  745. # register.filter('somename', somefunc)
  746. self.filters[name] = filter_func
  747. return filter_func
  748. else:
  749. raise InvalidTemplateLibrary("Unsupported arguments to Library.filter: (%r, %r)", (name, filter_func))
  750. def filter_function(self, func):
  751. self.filters[getattr(func, "_decorated_function", func).__name__] = func
  752. return func
  753. def simple_tag(self, func=None, takes_context=None):
  754. def dec(func):
  755. params, xx, xxx, defaults = getargspec(func)
  756. if takes_context:
  757. if params[0] == 'context':
  758. params = params[1:]
  759. else:
  760. raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
  761. class SimpleNode(Node):
  762. def __init__(self, vars_to_resolve):
  763. self.vars_to_resolve = map(Variable, vars_to_resolve)
  764. def render(self, context):
  765. resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
  766. if takes_context:
  767. func_args = [context] + resolved_vars
  768. else:
  769. func_args = resolved_vars
  770. return func(*func_args)
  771. compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode)
  772. compile_func.__doc__ = func.__doc__
  773. self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
  774. return func
  775. if func is None:
  776. # @register.simple_tag(...)
  777. return dec
  778. elif callable(func):
  779. # @register.simple_tag
  780. return dec(func)
  781. else:
  782. raise TemplateSyntaxError("Invalid arguments provided to simple_tag")
  783. def inclusion_tag(self, file_name, context_class=Context, takes_context=False):
  784. def dec(func):
  785. params, xx, xxx, defaults = getargspec(func)
  786. if takes_context:
  787. if params[0] == 'context':
  788. params = params[1:]
  789. else:
  790. raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
  791. class InclusionNode(Node):
  792. def __init__(self, vars_to_resolve):
  793. self.vars_to_resolve = map(Variable, vars_to_resolve)
  794. def render(self, context):
  795. resolved_vars = [var.resolve(context) for var in self.vars_to_resolve]
  796. if takes_context:
  797. args = [context] + resolved_vars
  798. else:
  799. args = resolved_vars
  800. dict = func(*args)
  801. if not getattr(self, 'nodelist', False):
  802. from django.template.loader import get_template, select_template
  803. if not isinstance(file_name, basestring) and is_iterable(file_name):
  804. t = select_template(file_name)
  805. else:
  806. t = get_template(file_name)
  807. self.nodelist = t.nodelist
  808. new_context = context_class(dict, autoescape=context.autoescape)
  809. # Copy across the CSRF token, if present, because inclusion
  810. # tags are often used for forms, and we need instructions
  811. # for using CSRF protection to be as simple as possible.
  812. csrf_token = context.get('csrf_token', None)
  813. if csrf_token is not None:
  814. new_context['csrf_token'] = csrf_token
  815. return self.nodelist.render(new_context)
  816. compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
  817. compile_func.__doc__ = func.__doc__
  818. self.tag(getattr(func, "_decorated_function", func).__name__, compile_func)
  819. return func
  820. return dec
  821. def import_library(taglib_module):
  822. """Load a template tag library module.
  823. Verifies that the library contains a 'register' attribute, and
  824. returns that attribute as the representation of the library
  825. """
  826. app_path, taglib = taglib_module.rsplit('.',1)
  827. app_module = import_module(app_path)
  828. try:
  829. mod = import_module(taglib_module)
  830. except ImportError, e:
  831. # If the ImportError is because the taglib submodule does not exist, that's not
  832. # an error that should be raised. If the submodule exists and raised an ImportError
  833. # on the attempt to load it, that we want to raise.
  834. if not module_has_submodule(app_module, taglib):
  835. return None
  836. else:
  837. raise InvalidTemplateLibrary("ImportError raised loading %s: %s" % (taglib_module, e))
  838. try:
  839. return mod.register
  840. except AttributeError:
  841. raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % taglib_module)
  842. templatetags_modules = []
  843. def get_templatetags_modules():
  844. """Return the list of all available template tag modules.
  845. Caches the result for faster access.
  846. """
  847. global templatetags_modules
  848. if not templatetags_modules:
  849. _templatetags_modules = []
  850. # Populate list once per thread.
  851. for app_module in ['django'] + list(settings.INSTALLED_APPS):
  852. try:
  853. templatetag_module = '%s.templatetags' % app_module
  854. import_module(templatetag_module)
  855. _templatetags_modules.append(templatetag_module)
  856. except ImportError:
  857. continue
  858. templatetags_modules = _templatetags_modules
  859. return templatetags_modules
  860. def get_library(library_name):
  861. """
  862. Load the template library module with the given name.
  863. If library is not already loaded loop over all templatetags modules to locate it.
  864. {% load somelib %} and {% load someotherlib %} loops twice.
  865. Subsequent loads eg. {% load somelib %} in the same process will grab the cached
  866. module from libraries.
  867. """
  868. lib = libraries.get(library_name, None)
  869. if not lib:
  870. templatetags_modules = get_templatetags_modules()
  871. tried_modules = []
  872. for module in templatetags_modules:
  873. taglib_module = '%s.%s' % (module, library_name)
  874. tried_modules.append(taglib_module)
  875. lib = import_library(taglib_module)
  876. if lib:
  877. libraries[library_name] = lib
  878. break
  879. if not lib:
  880. raise InvalidTemplateLibrary("Template library %s not found, tried %s" % (library_name, ','.join(tried_modules)))
  881. return lib
  882. def add_to_builtins(module):
  883. builtins.append(import_library(module))
  884. add_to_builtins('django.template.defaulttags')
  885. add_to_builtins('django.template.defaultfilters')