sekizai.helpers: 88 total statements, 0.0% covered

Generated: Wed 2013-03-13 10:33 CET

Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/sekizai/helpers.py

Stats: 0 executed, 83 missed, 5 excluded, 48 ignored

  1. # -*- coding: utf-8 -*-
  2. from django.conf import settings
  3. from django.template import VariableNode, Variable
  4. from django.template.loader import get_template
  5. from django.template.loader_tags import BlockNode, ExtendsNode
  6. def is_variable_extend_node(node):
  7. if hasattr(node, 'parent_name_expr') and node.parent_name_expr:
  8. return True
  9. if hasattr(node, 'parent_name') and hasattr(node.parent_name, 'filters'):
  10. if node.parent_name.filters or isinstance(node.parent_name.var, Variable):
  11. return True
  12. return False
  13. def _extend_blocks(extend_node, blocks):
  14. """
  15. Extends the dictionary `blocks` with *new* blocks in the parent node (recursive)
  16. """
  17. # we don't support variable extensions
  18. if is_variable_extend_node(extend_node):
  19. return
  20. parent = extend_node.get_parent(None)
  21. # Search for new blocks
  22. for node in parent.nodelist.get_nodes_by_type(BlockNode):
  23. if not node.name in blocks:
  24. blocks[node.name] = node
  25. else:
  26. # set this node as the super node (for {{ block.super }})
  27. block = blocks[node.name]
  28. seen_supers = []
  29. while hasattr(block.super, 'nodelist') and block.super not in seen_supers:
  30. seen_supers.append(block.super)
  31. block = block.super
  32. block.super = node
  33. # search for further ExtendsNodes
  34. for node in parent.nodelist.get_nodes_by_type(ExtendsNode):
  35. _extend_blocks(node, blocks)
  36. break
  37. def _extend_nodelist(extend_node):
  38. """
  39. Returns a list of namespaces found in the parent template(s) of this
  40. ExtendsNode
  41. """
  42. # we don't support variable extensions (1.3 way)
  43. if is_variable_extend_node(extend_node):
  44. return []
  45. blocks = extend_node.blocks
  46. _extend_blocks(extend_node, blocks)
  47. found = []
  48. for block in blocks.values():
  49. found += _scan_namespaces(block.nodelist, block, blocks.keys())
  50. parent_template = extend_node.get_parent({})
  51. # if this is the topmost template, check for namespaces outside of blocks
  52. if not parent_template.nodelist.get_nodes_by_type(ExtendsNode):
  53. found += _scan_namespaces(parent_template.nodelist, None, blocks.keys())
  54. else:
  55. found += _scan_namespaces(parent_template.nodelist, extend_node, blocks.keys())
  56. return found
  57. def _scan_namespaces(nodelist, current_block=None, ignore_blocks=None):
  58. from sekizai.templatetags.sekizai_tags import RenderBlock
  59. if ignore_blocks is None:
  60. ignore_blocks = []
  61. found = []
  62. for node in nodelist:
  63. # check if this is RenderBlock node
  64. if isinstance(node, RenderBlock):
  65. # resolve it's name against a dummy context
  66. found.append(node.kwargs['name'].resolve({}))
  67. found += _scan_namespaces(node.blocks['nodelist'], node)
  68. # handle {% extends ... %} tags if check_inheritance is True
  69. elif isinstance(node, ExtendsNode):
  70. found += _extend_nodelist(node)
  71. # in block nodes we have to scan for super blocks
  72. elif isinstance(node, VariableNode) and current_block:
  73. if node.filter_expression.token == 'block.super':
  74. if hasattr(current_block.super, 'nodelist'):
  75. found += _scan_namespaces(current_block.super.nodelist, current_block.super)
  76. return found
  77. def get_namespaces(template):
  78. compiled_template = get_template(template)
  79. return _scan_namespaces(compiled_template.nodelist)
  80. def validate_template(template, namespaces):
  81. """
  82. Validates that a template (or it's parents if check_inheritance is True)
  83. contain all given namespaces
  84. """
  85. if getattr(settings, 'SEKIZAI_IGNORE_VALIDATION', False):
  86. return True
  87. found = get_namespaces(template)
  88. for namespace in namespaces:
  89. if namespace not in found:
  90. return False
  91. return True
  92. def get_varname():
  93. return getattr(settings, 'SEKIZAI_VARNAME', 'SEKIZAI_CONTENT_HOLDER')
  94. class Watcher(object):
  95. """
  96. Watches a context for changes to the sekizai data, so it can be replayed later.
  97. This is useful for caching.
  98. NOTE: This class assumes you ONLY ADD, NEVER REMOVE data from the context!
  99. """
  100. def __init__(self, context):
  101. self.context = context
  102. self.frozen = dict((key, list(value)) for key, value in self.data.items())
  103. @property
  104. def data(self):
  105. return self.context.get(get_varname(), {})
  106. def get_changes(self):
  107. sfrozen = set(self.frozen)
  108. sdata = set(self.data)
  109. new_keys = sfrozen ^ sdata
  110. changes = {}
  111. for key in new_keys:
  112. changes[key] = list(self.data[key])
  113. shared_keys = sfrozen & sdata
  114. for key in shared_keys:
  115. old_set = set(self.frozen[key])
  116. new_values = [item for item in self.data[key] if item not in old_set]
  117. changes[key] = new_values
  118. return changes