/usr/lib/python2.7/dist-packages/sekizai/helpers.py is in python-django-sekizai 0.9.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | # -*- coding: utf-8 -*-
from django.conf import settings
from django.template.base import VariableNode, Variable, Context, Template
from django.template.loader import get_template
from django.template.loader_tags import BlockNode, ExtendsNode
try:
from django.template import engines
except ImportError:
engines = None
def _get_nodelist(tpl):
if isinstance(tpl, Template):
return tpl.nodelist
else:
return tpl.template.nodelist
def is_variable_extend_node(node):
if hasattr(node, 'parent_name_expr') and node.parent_name_expr:
return True
if hasattr(node, 'parent_name') and hasattr(node.parent_name, 'filters'):
if (node.parent_name.filters or
isinstance(node.parent_name.var, Variable)):
return True
return False
def get_context():
if engines is not None:
context = Context()
context.template = Template('')
return context
else:
return Context()
def _extend_blocks(extend_node, blocks):
"""
Extends the dictionary `blocks` with *new* blocks in the parent node
(recursive)
"""
# we don't support variable extensions
if is_variable_extend_node(extend_node):
return
parent = extend_node.get_parent(get_context())
# Search for new blocks
for node in _get_nodelist(parent).get_nodes_by_type(BlockNode):
if node.name not in blocks:
blocks[node.name] = node
else:
# set this node as the super node (for {{ block.super }})
block = blocks[node.name]
seen_supers = []
while (hasattr(block.super, 'nodelist') and
block.super not in seen_supers):
seen_supers.append(block.super)
block = block.super
block.super = node
# search for further ExtendsNodes
for node in _get_nodelist(parent).get_nodes_by_type(ExtendsNode):
_extend_blocks(node, blocks)
break
def _extend_nodelist(extend_node):
"""
Returns a list of namespaces found in the parent template(s) of this
ExtendsNode
"""
# we don't support variable extensions (1.3 way)
if is_variable_extend_node(extend_node):
return []
blocks = extend_node.blocks
_extend_blocks(extend_node, blocks)
found = []
for block in blocks.values():
found += _scan_namespaces(block.nodelist, block)
parent_template = extend_node.get_parent(get_context())
# if this is the topmost template, check for namespaces outside of blocks
if not _get_nodelist(parent_template).get_nodes_by_type(ExtendsNode):
found += _scan_namespaces(
_get_nodelist(parent_template),
None
)
else:
found += _scan_namespaces(
_get_nodelist(parent_template),
extend_node
)
return found
def _scan_namespaces(nodelist, current_block=None):
from sekizai.templatetags.sekizai_tags import RenderBlock
found = []
for node in nodelist:
# check if this is RenderBlock node
if isinstance(node, RenderBlock):
# resolve it's name against a dummy context
found.append(node.kwargs['name'].resolve({}))
found += _scan_namespaces(node.blocks['nodelist'], node)
# handle {% extends ... %} tags if check_inheritance is True
elif isinstance(node, ExtendsNode):
found += _extend_nodelist(node)
# in block nodes we have to scan for super blocks
elif isinstance(node, VariableNode) and current_block:
if node.filter_expression.token == 'block.super':
if hasattr(current_block.super, 'nodelist'):
found += _scan_namespaces(
current_block.super.nodelist,
current_block.super
)
return found
def get_namespaces(template):
compiled_template = get_template(template)
return _scan_namespaces(_get_nodelist(compiled_template))
def validate_template(template, namespaces):
"""
Validates that a template (or it's parents if check_inheritance is True)
contain all given namespaces
"""
if getattr(settings, 'SEKIZAI_IGNORE_VALIDATION', False):
return True
found = get_namespaces(template)
for namespace in namespaces:
if namespace not in found:
return False
return True
def get_varname():
return getattr(settings, 'SEKIZAI_VARNAME', 'SEKIZAI_CONTENT_HOLDER')
class Watcher(object):
"""
Watches a context for changes to the sekizai data, so it can be replayed
later. This is useful for caching.
NOTE: This class assumes you ONLY ADD, NEVER REMOVE data from the context!
"""
def __init__(self, context):
self.context = context
self.frozen = dict(
(key, list(value)) for key, value in self.data.items()
)
@property
def data(self):
return self.context.get(get_varname(), {})
def get_changes(self):
sfrozen = set(self.frozen)
sdata = set(self.data)
new_keys = sfrozen ^ sdata
changes = {}
for key in new_keys:
changes[key] = list(self.data[key])
shared_keys = sfrozen & sdata
for key in shared_keys:
old_set = set(self.frozen[key])
new_values = [
item for item in self.data[key] if item not in old_set
]
changes[key] = new_values
return changes
|