simplified template.py

This commit is contained in:
mdipierro
2012-08-28 21:11:27 -05:00
parent 6b606aaa24
commit 5daf7e5a9b
3 changed files with 68 additions and 136 deletions
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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