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 == '':
|
if name is None or name == '':
|
||||||
return True
|
return True
|
||||||
name = str(name)
|
name = str(name)
|
||||||
|
request_vars_get = self.request_vars.get
|
||||||
if self['_type'] != 'checkbox':
|
if self['_type'] != 'checkbox':
|
||||||
self['old_value'] = self['value'] or self['_value'] or ''
|
self['old_value'] = self['value'] or self['_value'] or ''
|
||||||
value = self.request_vars.get(name, '')
|
value = request_vars_get(name, '')
|
||||||
self['value'] = value
|
self['value'] = value
|
||||||
else:
|
else:
|
||||||
self['old_value'] = self['value'] or False
|
self['old_value'] = self['value'] or False
|
||||||
value = self.request_vars.get(name)
|
value = request_vars_get(name)
|
||||||
if isinstance(value, (tuple, list)):
|
if isinstance(value, (tuple, list)):
|
||||||
self['value'] = self['_value'] in value
|
self['value'] = self['_value'] in value
|
||||||
else:
|
else:
|
||||||
@@ -1936,14 +1936,15 @@ class FORM(DIV):
|
|||||||
# check formname and formkey
|
# check formname and formkey
|
||||||
|
|
||||||
status = True
|
status = True
|
||||||
if self.session:
|
request_vars = self.request_vars
|
||||||
formkey = self.session.get('_formkey[%s]' % self.formname, None)
|
if session:
|
||||||
|
formkey = session.get('_formkey[%s]' % formname, None)
|
||||||
# check if user tampering with form and void CSRF
|
# check if user tampering with form and void CSRF
|
||||||
if formkey != self.request_vars._formkey:
|
if formkey != request_vars._formkey:
|
||||||
status = False
|
status = False
|
||||||
if self.formname != self.request_vars._formname:
|
if formname != request_vars._formname:
|
||||||
status = False
|
status = False
|
||||||
if status and self.session:
|
if status and session:
|
||||||
# check if editing a record that has been modified by the server
|
# check if editing a record that has been modified by the server
|
||||||
if hasattr(self,'record_hash') and self.record_hash != formkey:
|
if hasattr(self,'record_hash') and self.record_hash != formkey:
|
||||||
status = False
|
status = False
|
||||||
|
|||||||
+58
-127
@@ -15,10 +15,10 @@ Contributors:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import cgi
|
import cgi
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import logging
|
import logging
|
||||||
|
from re import compile, sub, escape, DOTALL
|
||||||
try:
|
try:
|
||||||
# have web2py
|
# have web2py
|
||||||
from restricted import RestrictedError
|
from restricted import RestrictedError
|
||||||
@@ -57,6 +57,18 @@ class SuperNode(Node):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s->%s" % (self.name, self.value)
|
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):
|
class BlockNode(Node):
|
||||||
"""
|
"""
|
||||||
Block Container.
|
Block Container.
|
||||||
@@ -81,8 +93,7 @@ class BlockNode(Node):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
lines = ['%sblock %s%s' % (self.left,self.name,self.right)]
|
lines = ['%sblock %s%s' % (self.left,self.name,self.right)]
|
||||||
for node in self.nodes:
|
lines += [str(node) for node in self.nodes]
|
||||||
lines.append(str(node))
|
|
||||||
lines.append('%send%s' % (self.left, self.right))
|
lines.append('%send%s' % (self.left, self.right))
|
||||||
return ''.join(lines)
|
return ''.join(lines)
|
||||||
|
|
||||||
@@ -90,11 +101,8 @@ class BlockNode(Node):
|
|||||||
"""
|
"""
|
||||||
Get this BlockNodes content, not including child Nodes
|
Get this BlockNodes content, not including child Nodes
|
||||||
"""
|
"""
|
||||||
lines = []
|
return ''.join(str(node) for node in self.nodes \
|
||||||
for node in self.nodes:
|
if not isinstance(node, BlockNode))
|
||||||
if not isinstance(node, BlockNode):
|
|
||||||
lines.append(str(node))
|
|
||||||
return ''.join(lines)
|
|
||||||
|
|
||||||
def append(self, node):
|
def append(self, node):
|
||||||
"""
|
"""
|
||||||
@@ -122,30 +130,14 @@ class BlockNode(Node):
|
|||||||
else:
|
else:
|
||||||
raise TypeError("Invalid type; must be instance of ``BlockNode``. %s" % other)
|
raise TypeError("Invalid type; must be instance of ``BlockNode``. %s" % other)
|
||||||
|
|
||||||
|
|
||||||
def output(self, blocks):
|
def output(self, blocks):
|
||||||
"""
|
"""
|
||||||
Merges all nodes into a single string.
|
Merges all nodes into a single string.
|
||||||
|
|
||||||
blocks -- Dictionary of blocks that are extending
|
blocks -- Dictionary of blocks that are extending
|
||||||
from this template.
|
from this template.
|
||||||
"""
|
"""
|
||||||
lines = []
|
return ''.join(output_aux(node,blocks) for node in self.nodes)
|
||||||
# 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)
|
|
||||||
|
|
||||||
class Content(BlockNode):
|
class Content(BlockNode):
|
||||||
"""
|
"""
|
||||||
@@ -165,29 +157,13 @@ class Content(BlockNode):
|
|||||||
self.pre_extend = pre_extend
|
self.pre_extend = pre_extend
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
lines = []
|
return ''.join(output_aux(node,self.blocks) for node in self.nodes)
|
||||||
# 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)
|
|
||||||
|
|
||||||
def _insert(self, other, index = 0):
|
def _insert(self, other, index = 0):
|
||||||
"""
|
"""
|
||||||
Inserts object at index.
|
Inserts object at index.
|
||||||
"""
|
"""
|
||||||
if isinstance(other, str) or isinstance(other, Node):
|
if isinstance(other, (str, Node)):
|
||||||
self.nodes.insert(index, other)
|
self.nodes.insert(index, other)
|
||||||
else:
|
else:
|
||||||
raise TypeError("Invalid type, must be instance of ``str`` or ``Node``.")
|
raise TypeError("Invalid type, must be instance of ``str`` or ``Node``.")
|
||||||
@@ -201,8 +177,7 @@ class Content(BlockNode):
|
|||||||
if isinstance(other, (list, tuple)):
|
if isinstance(other, (list, tuple)):
|
||||||
# Must reverse so the order stays the same.
|
# Must reverse so the order stays the same.
|
||||||
other.reverse()
|
other.reverse()
|
||||||
for item in other:
|
(self._insert(item, index) for item in other)
|
||||||
self._insert(item, index)
|
|
||||||
else:
|
else:
|
||||||
self._insert(other, index)
|
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.
|
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)
|
self.nodes.append(node)
|
||||||
if isinstance(node, BlockNode):
|
if isinstance(node, BlockNode):
|
||||||
self.blocks[node.name] = node
|
self.blocks[node.name] = node
|
||||||
@@ -233,18 +208,18 @@ class Content(BlockNode):
|
|||||||
class TemplateParser(object):
|
class TemplateParser(object):
|
||||||
|
|
||||||
default_delimiters = ('{{','}}')
|
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.
|
# These are used for re-indentation.
|
||||||
# Indent + 1
|
# Indent + 1
|
||||||
re_block = re.compile('^(elif |else:|except:|except |finally:).*$',
|
re_block = compile('^(elif |else:|except:|except |finally:).*$',DOTALL)
|
||||||
re.DOTALL)
|
|
||||||
# Indent - 1
|
# Indent - 1
|
||||||
re_unblock = re.compile('^(return|continue|break|raise)( .*)?$', re.DOTALL)
|
re_unblock = compile('^(return|continue|break|raise)( .*)?$', DOTALL)
|
||||||
# Indent - 1
|
# Indent - 1
|
||||||
re_pass = re.compile('^pass( .*)?$', re.DOTALL)
|
re_pass = compile('^pass( .*)?$', DOTALL)
|
||||||
|
|
||||||
def __init__(self, text,
|
def __init__(self, text,
|
||||||
name = "ParserContainer",
|
name = "ParserContainer",
|
||||||
@@ -291,13 +266,16 @@ class TemplateParser(object):
|
|||||||
# allow optional alternative delimiters
|
# allow optional alternative delimiters
|
||||||
self.delimiters = delimiters
|
self.delimiters = delimiters
|
||||||
if delimiters != self.default_delimiters:
|
if delimiters != self.default_delimiters:
|
||||||
escaped_delimiters = (re.escape(delimiters[0]),re.escape(delimiters[1]))
|
escaped_delimiters = (escape(delimiters[0]),
|
||||||
self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters, re.DOTALL)
|
escape(delimiters[1]))
|
||||||
|
self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters, DOTALL)
|
||||||
elif hasattr(context.get('response',None),'delimiters'):
|
elif hasattr(context.get('response',None),'delimiters'):
|
||||||
if context['response'].delimiters != self.default_delimiters:
|
if context['response'].delimiters != self.default_delimiters:
|
||||||
escaped_delimiters = (re.escape(context['response'].delimiters[0]),
|
escaped_delimiters = (
|
||||||
re.escape(context['response'].delimiters[1]))
|
escape(context['response'].delimiters[0]),
|
||||||
self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters,re.DOTALL)
|
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.
|
# Create a root level Content that everything will go into.
|
||||||
self.content = Content(name=name)
|
self.content = Content(name=name)
|
||||||
@@ -524,17 +502,19 @@ class TemplateParser(object):
|
|||||||
# the parent nodes.
|
# the parent nodes.
|
||||||
self.content.nodes = []
|
self.content.nodes = []
|
||||||
|
|
||||||
|
t_content = t.content
|
||||||
|
|
||||||
# Set our include, unique by filename
|
# 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
|
# Make sure our pre_extended nodes go first
|
||||||
t.content.insert(pre)
|
t_content.insert(pre)
|
||||||
|
|
||||||
# Then we extend our blocks
|
# Then we extend our blocks
|
||||||
t.content.extend(self.content)
|
t_content.extend(self.content)
|
||||||
|
|
||||||
# Work off the parent node.
|
# Work off the parent node.
|
||||||
self.content = t.content
|
self.content = t_content
|
||||||
|
|
||||||
def parse(self, text):
|
def parse(self, text):
|
||||||
|
|
||||||
@@ -553,69 +533,20 @@ class TemplateParser(object):
|
|||||||
ij = self.r_tag.split(text)
|
ij = self.r_tag.split(text)
|
||||||
# j = current index
|
# j = current index
|
||||||
# i = current item
|
# i = current item
|
||||||
|
stack = self.stack
|
||||||
for j in range(len(ij)):
|
for j in range(len(ij)):
|
||||||
i = ij[j]
|
i = ij[j]
|
||||||
|
|
||||||
if i:
|
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')
|
self._raise_error('The "end" tag is unmatched, please check if you have a starting "block" tag')
|
||||||
|
|
||||||
# Our current element in the stack.
|
# Our current element in the stack.
|
||||||
top = self.stack[-1]
|
top = stack[-1]
|
||||||
|
|
||||||
if in_tag:
|
if in_tag:
|
||||||
line = i
|
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 '}}'
|
# Get rid of '{{' and '}}'
|
||||||
line = line[2:-2].strip()
|
line = line[2:-2].strip()
|
||||||
|
|
||||||
@@ -633,9 +564,9 @@ class TemplateParser(object):
|
|||||||
# Perform block comment escaping.
|
# Perform block comment escaping.
|
||||||
# This performs escaping ON anything
|
# This performs escaping ON anything
|
||||||
# in between """ and """
|
# in between """ and """
|
||||||
line = re.sub(TemplateParser.r_multiline,
|
line = sub(TemplateParser.r_multiline,
|
||||||
remove_newline,
|
remove_newline,
|
||||||
line)
|
line)
|
||||||
|
|
||||||
if line.startswith('='):
|
if line.startswith('='):
|
||||||
# IE: {{=response.title}}
|
# IE: {{=response.title}}
|
||||||
@@ -672,7 +603,7 @@ class TemplateParser(object):
|
|||||||
self.lexers[name](parser = self,
|
self.lexers[name](parser = self,
|
||||||
value = value,
|
value = value,
|
||||||
top = top,
|
top = top,
|
||||||
stack = self.stack,)
|
stack = stack)
|
||||||
|
|
||||||
elif name == '=':
|
elif name == '=':
|
||||||
# So we have a variable to insert into
|
# So we have a variable to insert into
|
||||||
@@ -693,7 +624,7 @@ class TemplateParser(object):
|
|||||||
# so anything after this gets added
|
# so anything after this gets added
|
||||||
# to this node. This allows us to
|
# to this node. This allows us to
|
||||||
# "nest" nodes.
|
# "nest" nodes.
|
||||||
self.stack.append(node)
|
stack.append(node)
|
||||||
|
|
||||||
elif name == 'end' and not value.startswith('='):
|
elif name == 'end' and not value.startswith('='):
|
||||||
# We are done with this node.
|
# We are done with this node.
|
||||||
@@ -702,7 +633,7 @@ class TemplateParser(object):
|
|||||||
self.blocks[top.name] = top
|
self.blocks[top.name] = top
|
||||||
|
|
||||||
# Pop it.
|
# Pop it.
|
||||||
self.stack.pop()
|
stack.pop()
|
||||||
|
|
||||||
elif name == 'super' and not value.startswith('='):
|
elif name == 'super' and not value.startswith('='):
|
||||||
# Get our correct target name
|
# Get our correct target name
|
||||||
@@ -757,17 +688,17 @@ class TemplateParser(object):
|
|||||||
# So we can properly put a response.write() in place.
|
# So we can properly put a response.write() in place.
|
||||||
continuation = False
|
continuation = False
|
||||||
len_parsed = 0
|
len_parsed = 0
|
||||||
for k in range(len(tokens)):
|
for k, token in enumerate(tokens):
|
||||||
|
|
||||||
tokens[k] = tokens[k].strip()
|
token = tokens[k] = token.strip()
|
||||||
len_parsed += len(tokens[k])
|
len_parsed += len(token)
|
||||||
|
|
||||||
if tokens[k].startswith('='):
|
if token.startswith('='):
|
||||||
if tokens[k].endswith('\\'):
|
if token.endswith('\\'):
|
||||||
continuation = True
|
continuation = True
|
||||||
tokens[k] = "\n%s(%s" % (self.writer, tokens[k][1:].strip())
|
tokens[k] = "\n%s(%s" % (self.writer, token[1:].strip())
|
||||||
else:
|
else:
|
||||||
tokens[k] = "\n%s(%s)" % (self.writer, tokens[k][1:].strip())
|
tokens[k] = "\n%s(%s)" % (self.writer, token[1:].strip())
|
||||||
elif continuation:
|
elif continuation:
|
||||||
tokens[k] += ')'
|
tokens[k] += ')'
|
||||||
continuation = False
|
continuation = False
|
||||||
|
|||||||
Reference in New Issue
Block a user