simplified template.py
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 2.00.1 (2012-08-28 20:38:06) rc4
|
||||
Version 2.00.1 (2012-08-28 21:11:21) rc4
|
||||
|
||||
+9
-8
@@ -1686,14 +1686,14 @@ class INPUT(DIV):
|
||||
if name is None or name == '':
|
||||
return True
|
||||
name = str(name)
|
||||
|
||||
request_vars_get = self.request_vars.get
|
||||
if self['_type'] != 'checkbox':
|
||||
self['old_value'] = self['value'] or self['_value'] or ''
|
||||
value = self.request_vars.get(name, '')
|
||||
value = request_vars_get(name, '')
|
||||
self['value'] = value
|
||||
else:
|
||||
self['old_value'] = self['value'] or False
|
||||
value = self.request_vars.get(name)
|
||||
value = request_vars_get(name)
|
||||
if isinstance(value, (tuple, list)):
|
||||
self['value'] = self['_value'] in value
|
||||
else:
|
||||
@@ -1936,14 +1936,15 @@ class FORM(DIV):
|
||||
# check formname and formkey
|
||||
|
||||
status = True
|
||||
if self.session:
|
||||
formkey = self.session.get('_formkey[%s]' % self.formname, None)
|
||||
request_vars = self.request_vars
|
||||
if session:
|
||||
formkey = session.get('_formkey[%s]' % formname, None)
|
||||
# check if user tampering with form and void CSRF
|
||||
if formkey != self.request_vars._formkey:
|
||||
if formkey != request_vars._formkey:
|
||||
status = False
|
||||
if self.formname != self.request_vars._formname:
|
||||
if formname != request_vars._formname:
|
||||
status = False
|
||||
if status and self.session:
|
||||
if status and session:
|
||||
# check if editing a record that has been modified by the server
|
||||
if hasattr(self,'record_hash') and self.record_hash != formkey:
|
||||
status = False
|
||||
|
||||
+58
-127
@@ -15,10 +15,10 @@ Contributors:
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import cgi
|
||||
import cStringIO
|
||||
import logging
|
||||
from re import compile, sub, escape, DOTALL
|
||||
try:
|
||||
# have web2py
|
||||
from restricted import RestrictedError
|
||||
@@ -57,6 +57,18 @@ class SuperNode(Node):
|
||||
def __repr__(self):
|
||||
return "%s->%s" % (self.name, self.value)
|
||||
|
||||
def output_aux(node,blocks):
|
||||
# If we have a block level
|
||||
# If we can override this block.
|
||||
# Override block from vars.
|
||||
# Else we take the default
|
||||
# Else its just a string
|
||||
return (blocks[node.name].output(blocks)
|
||||
if node.name in blocks else
|
||||
node.output(blocks)) \
|
||||
if isinstance(node, BlockNode) \
|
||||
else str(node)
|
||||
|
||||
class BlockNode(Node):
|
||||
"""
|
||||
Block Container.
|
||||
@@ -81,8 +93,7 @@ class BlockNode(Node):
|
||||
|
||||
def __repr__(self):
|
||||
lines = ['%sblock %s%s' % (self.left,self.name,self.right)]
|
||||
for node in self.nodes:
|
||||
lines.append(str(node))
|
||||
lines += [str(node) for node in self.nodes]
|
||||
lines.append('%send%s' % (self.left, self.right))
|
||||
return ''.join(lines)
|
||||
|
||||
@@ -90,11 +101,8 @@ class BlockNode(Node):
|
||||
"""
|
||||
Get this BlockNodes content, not including child Nodes
|
||||
"""
|
||||
lines = []
|
||||
for node in self.nodes:
|
||||
if not isinstance(node, BlockNode):
|
||||
lines.append(str(node))
|
||||
return ''.join(lines)
|
||||
return ''.join(str(node) for node in self.nodes \
|
||||
if not isinstance(node, BlockNode))
|
||||
|
||||
def append(self, node):
|
||||
"""
|
||||
@@ -122,30 +130,14 @@ class BlockNode(Node):
|
||||
else:
|
||||
raise TypeError("Invalid type; must be instance of ``BlockNode``. %s" % other)
|
||||
|
||||
|
||||
def output(self, blocks):
|
||||
"""
|
||||
Merges all nodes into a single string.
|
||||
|
||||
blocks -- Dictionary of blocks that are extending
|
||||
from this template.
|
||||
"""
|
||||
lines = []
|
||||
# Get each of our nodes
|
||||
for node in self.nodes:
|
||||
# If we have a block level node.
|
||||
if isinstance(node, BlockNode):
|
||||
# If we can override this block.
|
||||
if node.name in blocks:
|
||||
# Override block from vars.
|
||||
lines.append(blocks[node.name].output(blocks))
|
||||
# Else we take the default
|
||||
else:
|
||||
lines.append(node.output(blocks))
|
||||
# Else its just a string
|
||||
else:
|
||||
lines.append(str(node))
|
||||
# Now combine all of our lines together.
|
||||
return ''.join(lines)
|
||||
return ''.join(output_aux(node,blocks) for node in self.nodes)
|
||||
|
||||
class Content(BlockNode):
|
||||
"""
|
||||
@@ -165,29 +157,13 @@ class Content(BlockNode):
|
||||
self.pre_extend = pre_extend
|
||||
|
||||
def __str__(self):
|
||||
lines = []
|
||||
# For each of our nodes
|
||||
for node in self.nodes:
|
||||
# If it is a block node.
|
||||
if isinstance(node, BlockNode):
|
||||
# And the node has a name that corresponds with a block in us
|
||||
if node.name in self.blocks:
|
||||
# Use the overriding output.
|
||||
lines.append(self.blocks[node.name].output(self.blocks))
|
||||
else:
|
||||
# Otherwise we just use the nodes output.
|
||||
lines.append(node.output(self.blocks))
|
||||
else:
|
||||
# It is just a string, so include it.
|
||||
lines.append(str(node))
|
||||
# Merge our list together.
|
||||
return ''.join(lines)
|
||||
return ''.join(output_aux(node,self.blocks) for node in self.nodes)
|
||||
|
||||
def _insert(self, other, index = 0):
|
||||
"""
|
||||
Inserts object at index.
|
||||
"""
|
||||
if isinstance(other, str) or isinstance(other, Node):
|
||||
if isinstance(other, (str, Node)):
|
||||
self.nodes.insert(index, other)
|
||||
else:
|
||||
raise TypeError("Invalid type, must be instance of ``str`` or ``Node``.")
|
||||
@@ -201,8 +177,7 @@ class Content(BlockNode):
|
||||
if isinstance(other, (list, tuple)):
|
||||
# Must reverse so the order stays the same.
|
||||
other.reverse()
|
||||
for item in other:
|
||||
self._insert(item, index)
|
||||
(self._insert(item, index) for item in other)
|
||||
else:
|
||||
self._insert(other, index)
|
||||
|
||||
@@ -210,7 +185,7 @@ class Content(BlockNode):
|
||||
"""
|
||||
Adds a node to list. If it is a BlockNode then we assign a block for it.
|
||||
"""
|
||||
if isinstance(node, str) or isinstance(node, Node):
|
||||
if isinstance(node, (str, Node)):
|
||||
self.nodes.append(node)
|
||||
if isinstance(node, BlockNode):
|
||||
self.blocks[node.name] = node
|
||||
@@ -233,18 +208,18 @@ class Content(BlockNode):
|
||||
class TemplateParser(object):
|
||||
|
||||
default_delimiters = ('{{','}}')
|
||||
r_tag = re.compile(r'(\{\{.*?\}\})', re.DOTALL)
|
||||
r_tag = compile(r'(\{\{.*?\}\})', DOTALL)
|
||||
|
||||
r_multiline = re.compile(r'(""".*?""")|(\'\'\'.*?\'\'\')', re.DOTALL)
|
||||
r_multiline = compile(r'(""".*?""")|(\'\'\'.*?\'\'\')', DOTALL)
|
||||
|
||||
# These are used for re-indentation.
|
||||
# Indent + 1
|
||||
re_block = re.compile('^(elif |else:|except:|except |finally:).*$',
|
||||
re.DOTALL)
|
||||
re_block = compile('^(elif |else:|except:|except |finally:).*$',DOTALL)
|
||||
|
||||
# Indent - 1
|
||||
re_unblock = re.compile('^(return|continue|break|raise)( .*)?$', re.DOTALL)
|
||||
re_unblock = compile('^(return|continue|break|raise)( .*)?$', DOTALL)
|
||||
# Indent - 1
|
||||
re_pass = re.compile('^pass( .*)?$', re.DOTALL)
|
||||
re_pass = compile('^pass( .*)?$', DOTALL)
|
||||
|
||||
def __init__(self, text,
|
||||
name = "ParserContainer",
|
||||
@@ -291,13 +266,16 @@ class TemplateParser(object):
|
||||
# allow optional alternative delimiters
|
||||
self.delimiters = delimiters
|
||||
if delimiters != self.default_delimiters:
|
||||
escaped_delimiters = (re.escape(delimiters[0]),re.escape(delimiters[1]))
|
||||
self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters, re.DOTALL)
|
||||
escaped_delimiters = (escape(delimiters[0]),
|
||||
escape(delimiters[1]))
|
||||
self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters, DOTALL)
|
||||
elif hasattr(context.get('response',None),'delimiters'):
|
||||
if context['response'].delimiters != self.default_delimiters:
|
||||
escaped_delimiters = (re.escape(context['response'].delimiters[0]),
|
||||
re.escape(context['response'].delimiters[1]))
|
||||
self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters,re.DOTALL)
|
||||
escaped_delimiters = (
|
||||
escape(context['response'].delimiters[0]),
|
||||
escape(context['response'].delimiters[1]))
|
||||
self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters,
|
||||
DOTALL)
|
||||
|
||||
# Create a root level Content that everything will go into.
|
||||
self.content = Content(name=name)
|
||||
@@ -524,17 +502,19 @@ class TemplateParser(object):
|
||||
# the parent nodes.
|
||||
self.content.nodes = []
|
||||
|
||||
t_content = t.content
|
||||
|
||||
# Set our include, unique by filename
|
||||
t.content.blocks['__include__' + filename] = buf
|
||||
t_content.blocks['__include__' + filename] = buf
|
||||
|
||||
# Make sure our pre_extended nodes go first
|
||||
t.content.insert(pre)
|
||||
t_content.insert(pre)
|
||||
|
||||
# Then we extend our blocks
|
||||
t.content.extend(self.content)
|
||||
t_content.extend(self.content)
|
||||
|
||||
# Work off the parent node.
|
||||
self.content = t.content
|
||||
self.content = t_content
|
||||
|
||||
def parse(self, text):
|
||||
|
||||
@@ -553,69 +533,20 @@ class TemplateParser(object):
|
||||
ij = self.r_tag.split(text)
|
||||
# j = current index
|
||||
# i = current item
|
||||
stack = self.stack
|
||||
for j in range(len(ij)):
|
||||
i = ij[j]
|
||||
|
||||
if i:
|
||||
if len(self.stack) == 0:
|
||||
if not stack:
|
||||
self._raise_error('The "end" tag is unmatched, please check if you have a starting "block" tag')
|
||||
|
||||
# Our current element in the stack.
|
||||
top = self.stack[-1]
|
||||
top = stack[-1]
|
||||
|
||||
if in_tag:
|
||||
line = i
|
||||
|
||||
# If we are missing any strings!!!!
|
||||
# This usually happens with the following example
|
||||
# template code
|
||||
#
|
||||
# {{a = '}}'}}
|
||||
# or
|
||||
# {{a = '}}blahblah{{'}}
|
||||
#
|
||||
# This will fix these
|
||||
# This is commented out because the current template
|
||||
# system has this same limitation. Since this has a
|
||||
# performance hit on larger templates, I do not recommend
|
||||
# using this code on production systems. This is still here
|
||||
# for "i told you it *can* be fixed" purposes.
|
||||
#
|
||||
#
|
||||
# if line.count("'") % 2 != 0 or line.count('"') % 2 != 0:
|
||||
#
|
||||
# # Look ahead
|
||||
# la = 1
|
||||
# nextline = ij[j+la]
|
||||
#
|
||||
# # As long as we have not found our ending
|
||||
# # brackets keep going
|
||||
# while '}}' not in nextline:
|
||||
# la += 1
|
||||
# nextline += ij[j+la]
|
||||
# # clear this line, so we
|
||||
# # don't attempt to parse it
|
||||
# # this is why there is an "if i"
|
||||
# # around line 530
|
||||
# ij[j+la] = ''
|
||||
#
|
||||
# # retrieve our index.
|
||||
# index = nextline.index('}}')
|
||||
#
|
||||
# # Everything before the new brackets
|
||||
# before = nextline[:index+2]
|
||||
#
|
||||
# # Everything after
|
||||
# after = nextline[index+2:]
|
||||
#
|
||||
# # Make the next line everything after
|
||||
# # so it parses correctly, this *should* be
|
||||
# # all html
|
||||
# ij[j+1] = after
|
||||
#
|
||||
# # Add everything before to the current line
|
||||
# line += before
|
||||
|
||||
# Get rid of '{{' and '}}'
|
||||
line = line[2:-2].strip()
|
||||
|
||||
@@ -633,9 +564,9 @@ class TemplateParser(object):
|
||||
# Perform block comment escaping.
|
||||
# This performs escaping ON anything
|
||||
# in between """ and """
|
||||
line = re.sub(TemplateParser.r_multiline,
|
||||
remove_newline,
|
||||
line)
|
||||
line = sub(TemplateParser.r_multiline,
|
||||
remove_newline,
|
||||
line)
|
||||
|
||||
if line.startswith('='):
|
||||
# IE: {{=response.title}}
|
||||
@@ -672,7 +603,7 @@ class TemplateParser(object):
|
||||
self.lexers[name](parser = self,
|
||||
value = value,
|
||||
top = top,
|
||||
stack = self.stack,)
|
||||
stack = stack)
|
||||
|
||||
elif name == '=':
|
||||
# So we have a variable to insert into
|
||||
@@ -693,7 +624,7 @@ class TemplateParser(object):
|
||||
# so anything after this gets added
|
||||
# to this node. This allows us to
|
||||
# "nest" nodes.
|
||||
self.stack.append(node)
|
||||
stack.append(node)
|
||||
|
||||
elif name == 'end' and not value.startswith('='):
|
||||
# We are done with this node.
|
||||
@@ -702,7 +633,7 @@ class TemplateParser(object):
|
||||
self.blocks[top.name] = top
|
||||
|
||||
# Pop it.
|
||||
self.stack.pop()
|
||||
stack.pop()
|
||||
|
||||
elif name == 'super' and not value.startswith('='):
|
||||
# Get our correct target name
|
||||
@@ -757,17 +688,17 @@ class TemplateParser(object):
|
||||
# So we can properly put a response.write() in place.
|
||||
continuation = False
|
||||
len_parsed = 0
|
||||
for k in range(len(tokens)):
|
||||
for k, token in enumerate(tokens):
|
||||
|
||||
tokens[k] = tokens[k].strip()
|
||||
len_parsed += len(tokens[k])
|
||||
token = tokens[k] = token.strip()
|
||||
len_parsed += len(token)
|
||||
|
||||
if tokens[k].startswith('='):
|
||||
if tokens[k].endswith('\\'):
|
||||
if token.startswith('='):
|
||||
if token.endswith('\\'):
|
||||
continuation = True
|
||||
tokens[k] = "\n%s(%s" % (self.writer, tokens[k][1:].strip())
|
||||
tokens[k] = "\n%s(%s" % (self.writer, token[1:].strip())
|
||||
else:
|
||||
tokens[k] = "\n%s(%s)" % (self.writer, tokens[k][1:].strip())
|
||||
tokens[k] = "\n%s(%s)" % (self.writer, token[1:].strip())
|
||||
elif continuation:
|
||||
tokens[k] += ')'
|
||||
continuation = False
|
||||
|
||||
Reference in New Issue
Block a user