<s> """<STR_LIT>""" <EOL> import os <EOL> import cgi <EOL> import logging <EOL> from re import compile , sub , escape , DOTALL <EOL> try : <EOL> import cStringIO as StringIO <EOL> except : <EOL> from io import StringIO <EOL> try : <EOL> from gluon . restricted import RestrictedError <EOL> from gluon . globals import current <EOL> except ImportError : <EOL> current = None <EOL> def RestrictedError ( a , b , c ) : <EOL> logging . error ( str ( a ) + '<STR_LIT::>' + str ( b ) + '<STR_LIT::>' + str ( c ) ) <EOL> return RuntimeError <EOL> class Node ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , value = None , pre_extend = False ) : <EOL> self . value = value <EOL> self . pre_extend = pre_extend <EOL> def __str__ ( self ) : <EOL> return str ( self . value ) <EOL> class SuperNode ( Node ) : <EOL> def __init__ ( self , name = '<STR_LIT>' , pre_extend = False ) : <EOL> self . name = name <EOL> self . value = None <EOL> self . pre_extend = pre_extend <EOL> def __str__ ( self ) : <EOL> if self . value : <EOL> return str ( self . value ) <EOL> else : <EOL> return '<STR_LIT>' <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . name , self . value ) <EOL> def output_aux ( node , blocks ) : <EOL> return ( blocks [ node . name ] . output ( blocks ) <EOL> if node . name in blocks else <EOL> node . output ( blocks ) ) if isinstance ( node , BlockNode ) else str ( node ) <EOL> class BlockNode ( Node ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name = '<STR_LIT>' , pre_extend = False , delimiters = ( '<STR_LIT>' , '<STR_LIT>' ) ) : <EOL> """<STR_LIT>""" <EOL> self . nodes = [ ] <EOL> self . name = name <EOL> self . pre_extend = pre_extend <EOL> self . left , self . right = delimiters <EOL> def __repr__ ( self ) : <EOL> lines = [ '<STR_LIT>' % ( self . left , self . name , self . right ) ] <EOL> lines += [ str ( node ) for node in self . nodes ] <EOL> lines . append ( '<STR_LIT>' % ( self . left , self . right ) ) <EOL> return '<STR_LIT>' . join ( lines ) <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' . join ( str ( node ) for node in self . nodes <EOL> if not isinstance ( node , BlockNode ) ) <EOL> def append ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( node , str ) or isinstance ( node , Node ) : <EOL> self . nodes . append ( node ) <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" % node ) <EOL> def extend ( self , other ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( other , BlockNode ) : <EOL> self . nodes . extend ( other . nodes ) <EOL> else : <EOL> raise TypeError ( <EOL> "<STR_LIT>" % other ) <EOL> def output ( self , blocks ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' . join ( output_aux ( node , blocks ) for node in self . nodes ) <EOL> class Content ( BlockNode ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name = "<STR_LIT>" , pre_extend = False ) : <EOL> """<STR_LIT>""" <EOL> self . name = name <EOL> self . nodes = [ ] <EOL> self . blocks = { } <EOL> self . pre_extend = pre_extend <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' . join ( output_aux ( node , self . blocks ) for node in self . nodes ) <EOL> def _insert ( self , other , index = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( other , ( str , Node ) ) : <EOL> self . nodes . insert ( index , other ) <EOL> else : <EOL> raise TypeError ( <EOL> "<STR_LIT>" ) <EOL> def insert ( self , other , index = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( other , ( list , tuple ) ) : <EOL> other . reverse ( ) <EOL> for item in other : <EOL> self . _insert ( item , index ) <EOL> else : <EOL> self . _insert ( other , index ) <EOL> def append ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( node , ( str , Node ) ) : <EOL> self . nodes . append ( node ) <EOL> if isinstance ( node , BlockNode ) : <EOL> self . blocks [ node . name ] = node <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" % node ) <EOL> def extend ( self , other ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( other , BlockNode ) : <EOL> self . nodes . extend ( other . nodes ) <EOL> self . blocks . update ( other . blocks ) <EOL> else : <EOL> raise TypeError ( <EOL> "<STR_LIT>" % other ) <EOL> def clear_content ( self ) : <EOL> self . nodes = [ ] <EOL> class TemplateParser ( object ) : <EOL> default_delimiters = ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> r_tag = compile ( r'<STR_LIT>' , DOTALL ) <EOL> r_multiline = compile ( r'<STR_LIT>' , DOTALL ) <EOL> re_block = compile ( '<STR_LIT>' , DOTALL ) <EOL> re_unblock = compile ( '<STR_LIT>' , DOTALL ) <EOL> re_pass = compile ( '<STR_LIT>' , DOTALL ) <EOL> def __init__ ( self , text , <EOL> name = "<STR_LIT>" , <EOL> context = dict ( ) , <EOL> path = '<STR_LIT>' , <EOL> writer = '<STR_LIT>' , <EOL> lexers = { } , <EOL> delimiters = ( '<STR_LIT>' , '<STR_LIT>' ) , <EOL> _super_nodes = [ ] , <EOL> ) : <EOL> """<STR_LIT>""" <EOL> self . name = name <EOL> self . text = text <EOL> self . writer = writer <EOL> if isinstance ( lexers , dict ) : <EOL> self . lexers = lexers <EOL> else : <EOL> self . lexers = { } <EOL> self . path = path <EOL> self . context = context <EOL> self . delimiters = delimiters <EOL> if delimiters != self . default_delimiters : <EOL> escaped_delimiters = ( escape ( delimiters [ <NUM_LIT:0> ] ) , <EOL> escape ( delimiters [ <NUM_LIT:1> ] ) ) <EOL> self . r_tag = compile ( r'<STR_LIT>' % escaped_delimiters , DOTALL ) <EOL> elif hasattr ( context . get ( '<STR_LIT>' , None ) , '<STR_LIT>' ) : <EOL> if context [ '<STR_LIT>' ] . delimiters != self . default_delimiters : <EOL> escaped_delimiters = ( <EOL> escape ( context [ '<STR_LIT>' ] . delimiters [ <NUM_LIT:0> ] ) , <EOL> escape ( context [ '<STR_LIT>' ] . delimiters [ <NUM_LIT:1> ] ) ) <EOL> self . r_tag = compile ( r'<STR_LIT>' % escaped_delimiters , <EOL> DOTALL ) <EOL> self . content = Content ( name = name ) <EOL> self . stack = [ self . content ] <EOL> self . super_nodes = [ ] <EOL> self . child_super_nodes = _super_nodes <EOL> self . blocks = { } <EOL> self . parse ( text ) <EOL> def to_string ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . reindent ( str ( self . content ) ) <EOL> def __str__ ( self ) : <EOL> "<STR_LIT>" <EOL> return self . to_string ( ) <EOL> def __unicode__ ( self ) : <EOL> "<STR_LIT>" <EOL> return self . to_string ( ) <EOL> def reindent ( self , text ) : <EOL> """<STR_LIT>""" <EOL> lines = text . split ( '<STR_LIT:\n>' ) <EOL> new_lines = [ ] <EOL> credit = <NUM_LIT:0> <EOL> k = <NUM_LIT:0> <EOL> for raw_line in lines : <EOL> line = raw_line . strip ( ) <EOL> if not line : <EOL> continue <EOL> if TemplateParser . re_block . match ( line ) : <EOL> k = k + credit - <NUM_LIT:1> <EOL> k = max ( k , <NUM_LIT:0> ) <EOL> new_lines . append ( '<STR_LIT:U+0020>' * ( <NUM_LIT:4> * k ) + line ) <EOL> credit = <NUM_LIT:0> <EOL> if TemplateParser . re_pass . match ( line ) : <EOL> k -= <NUM_LIT:1> <EOL> if TemplateParser . re_unblock . match ( line ) : <EOL> credit = <NUM_LIT:1> <EOL> k -= <NUM_LIT:1> <EOL> if line . endswith ( '<STR_LIT::>' ) and not line . startswith ( '<STR_LIT:#>' ) : <EOL> k += <NUM_LIT:1> <EOL> new_text = '<STR_LIT:\n>' . join ( new_lines ) <EOL> if k > <NUM_LIT:0> : <EOL> self . _raise_error ( '<STR_LIT>' , new_text ) <EOL> elif k < <NUM_LIT:0> : <EOL> self . _raise_error ( '<STR_LIT>' , new_text ) <EOL> return new_text <EOL> def _raise_error ( self , message = '<STR_LIT>' , text = None ) : <EOL> """<STR_LIT>""" <EOL> raise RestrictedError ( self . name , text or self . text , message ) <EOL> def _get_file_text ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> if not filename . strip ( ) : <EOL> self . _raise_error ( '<STR_LIT>' ) <EOL> context = self . context <EOL> if current and not "<STR_LIT>" in context : <EOL> context [ "<STR_LIT>" ] = getattr ( current , '<STR_LIT>' , None ) <EOL> filename = eval ( filename , context ) <EOL> if not filename : <EOL> return '<STR_LIT>' <EOL> filepath = self . path and os . path . join ( self . path , filename ) or filename <EOL> try : <EOL> fileobj = open ( filepath , '<STR_LIT:rb>' ) <EOL> text = fileobj . read ( ) <EOL> fileobj . close ( ) <EOL> except IOError : <EOL> self . _raise_error ( '<STR_LIT>' + filepath ) <EOL> return text <EOL> def include ( self , content , filename ) : <EOL> """<STR_LIT>""" <EOL> text = self . _get_file_text ( filename ) <EOL> t = TemplateParser ( text , <EOL> name = filename , <EOL> context = self . context , <EOL> path = self . path , <EOL> writer = self . writer , <EOL> delimiters = self . delimiters ) <EOL> content . append ( t . content ) <EOL> def extend ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> text = self . _get_file_text ( filename ) or '<STR_LIT>' % tuple ( self . delimiters ) <EOL> super_nodes = [ ] <EOL> super_nodes . extend ( self . child_super_nodes ) <EOL> super_nodes . extend ( self . super_nodes ) <EOL> t = TemplateParser ( text , <EOL> name = filename , <EOL> context = self . context , <EOL> path = self . path , <EOL> writer = self . writer , <EOL> delimiters = self . delimiters , <EOL> _super_nodes = super_nodes ) <EOL> buf = BlockNode ( <EOL> name = '<STR_LIT>' + filename , delimiters = self . delimiters ) <EOL> pre = [ ] <EOL> for node in self . content . nodes : <EOL> if isinstance ( node , BlockNode ) : <EOL> if node . name in t . content . blocks : <EOL> continue <EOL> if isinstance ( node , Node ) : <EOL> if node . pre_extend : <EOL> pre . append ( node ) <EOL> continue <EOL> buf . append ( node ) <EOL> else : <EOL> buf . append ( node ) <EOL> self . content . nodes = [ ] <EOL> t_content = t . content <EOL> t_content . blocks [ '<STR_LIT>' + filename ] = buf <EOL> t_content . insert ( pre ) <EOL> t_content . extend ( self . content ) <EOL> self . content = t_content <EOL> def parse ( self , text ) : <EOL> in_tag = False <EOL> extend = None <EOL> pre_extend = True <EOL> ij = self . r_tag . split ( text ) <EOL> stack = self . stack <EOL> for j in range ( len ( ij ) ) : <EOL> i = ij [ j ] <EOL> if i : <EOL> if not stack : <EOL> self . _raise_error ( '<STR_LIT>' ) <EOL> top = stack [ - <NUM_LIT:1> ] <EOL> if in_tag : <EOL> line = i <EOL> line = line [ len ( self . delimiters [ <NUM_LIT:0> ] ) : - len ( self . delimiters [ <NUM_LIT:1> ] ) ] . strip ( ) <EOL> if not line : <EOL> continue <EOL> def remove_newline ( re_val ) : <EOL> return re_val . group ( <NUM_LIT:0> ) . replace ( '<STR_LIT:\n>' , '<STR_LIT>' ) <EOL> line = sub ( TemplateParser . r_multiline , <EOL> remove_newline , <EOL> line ) <EOL> if line . startswith ( '<STR_LIT:=>' ) : <EOL> name , value = '<STR_LIT:=>' , line [ <NUM_LIT:1> : ] . strip ( ) <EOL> else : <EOL> v = line . split ( '<STR_LIT:U+0020>' , <NUM_LIT:1> ) <EOL> if len ( v ) == <NUM_LIT:1> : <EOL> name = v [ <NUM_LIT:0> ] <EOL> value = '<STR_LIT>' <EOL> else : <EOL> name = v [ <NUM_LIT:0> ] <EOL> value = v [ <NUM_LIT:1> ] <EOL> if name in self . lexers : <EOL> self . lexers [ name ] ( parser = self , <EOL> value = value , <EOL> top = top , <EOL> stack = stack ) <EOL> elif name == '<STR_LIT:=>' : <EOL> buf = "<STR_LIT>" % ( self . writer , value ) <EOL> top . append ( Node ( buf , pre_extend = pre_extend ) ) <EOL> elif name == '<STR_LIT>' and not value . startswith ( '<STR_LIT:=>' ) : <EOL> node = BlockNode ( name = value . strip ( ) , <EOL> pre_extend = pre_extend , <EOL> delimiters = self . delimiters ) <EOL> top . append ( node ) <EOL> stack . append ( node ) <EOL> elif name == '<STR_LIT:end>' and not value . startswith ( '<STR_LIT:=>' ) : <EOL> self . blocks [ top . name ] = top <EOL> stack . pop ( ) <EOL> elif name == '<STR_LIT>' and not value . startswith ( '<STR_LIT:=>' ) : <EOL> if value : <EOL> target_node = value <EOL> else : <EOL> target_node = top . name <EOL> node = SuperNode ( name = target_node , <EOL> pre_extend = pre_extend ) <EOL> self . super_nodes . append ( node ) <EOL> top . append ( node ) <EOL> elif name == '<STR_LIT>' and not value . startswith ( '<STR_LIT:=>' ) : <EOL> if value : <EOL> self . include ( top , value ) <EOL> else : <EOL> include_node = BlockNode ( <EOL> name = '<STR_LIT>' + self . name , <EOL> pre_extend = pre_extend , <EOL> delimiters = self . delimiters ) <EOL> top . append ( include_node ) <EOL> elif name == '<STR_LIT>' and not value . startswith ( '<STR_LIT:=>' ) : <EOL> extend = value <EOL> pre_extend = False <EOL> else : <EOL> if line and in_tag : <EOL> tokens = line . split ( '<STR_LIT:\n>' ) <EOL> continuation = False <EOL> len_parsed = <NUM_LIT:0> <EOL> for k , token in enumerate ( tokens ) : <EOL> token = tokens [ k ] = token . strip ( ) <EOL> len_parsed += len ( token ) <EOL> if token . startswith ( '<STR_LIT:=>' ) : <EOL> if token . endswith ( '<STR_LIT:\\>' ) : <EOL> continuation = True <EOL> tokens [ k ] = "<STR_LIT>" % ( <EOL> self . writer , token [ <NUM_LIT:1> : ] . strip ( ) ) <EOL> else : <EOL> tokens [ k ] = "<STR_LIT>" % ( <EOL> self . writer , token [ <NUM_LIT:1> : ] . strip ( ) ) <EOL> elif continuation : <EOL> tokens [ k ] += '<STR_LIT:)>' <EOL> continuation = False <EOL> buf = "<STR_LIT>" % '<STR_LIT:\n>' . join ( tokens ) <EOL> top . append ( Node ( buf , pre_extend = pre_extend ) ) <EOL> else : <EOL> buf = "<STR_LIT>" % ( self . writer , i ) <EOL> top . append ( Node ( buf , pre_extend = pre_extend ) ) <EOL> in_tag = not in_tag <EOL> to_rm = [ ] <EOL> for node in self . child_super_nodes : <EOL> if node . name in self . blocks : <EOL> node . value = self . blocks [ node . name ] <EOL> to_rm . append ( node ) <EOL> for node in to_rm : <EOL> self . child_super_nodes . remove ( node ) <EOL> if extend : <EOL> self . extend ( extend ) <EOL> def parse_template ( filename , <EOL> path = '<STR_LIT>' , <EOL> context = dict ( ) , <EOL> lexers = { } , <EOL> delimiters = ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( filename , str ) : <EOL> try : <EOL> fp = open ( os . path . join ( path , filename ) , '<STR_LIT:rb>' ) <EOL> text = fp . read ( ) <EOL> fp . close ( ) <EOL> except IOError : <EOL> raise RestrictedError ( filename , '<STR_LIT>' , '<STR_LIT>' ) <EOL> else : <EOL> text = filename . read ( ) <EOL> return str ( TemplateParser ( text , context = context , path = path , lexers = lexers , delimiters = delimiters ) ) <EOL> def get_parsed ( text ) : <EOL> """<STR_LIT>""" <EOL> return str ( TemplateParser ( text ) ) <EOL> class DummyResponse ( ) : <EOL> def __init__ ( self ) : <EOL> self . body = StringIO . StringIO ( ) <EOL> def write ( self , data , escape = True ) : <EOL> if not escape : <EOL> self . body . write ( str ( data ) ) <EOL> elif hasattr ( data , '<STR_LIT>' ) and callable ( data . xml ) : <EOL> self . body . write ( data . xml ( ) ) <EOL> else : <EOL> if not isinstance ( data , ( str , unicode ) ) : <EOL> data = str ( data ) <EOL> elif isinstance ( data , unicode ) : <EOL> data = data . encode ( '<STR_LIT:utf8>' , '<STR_LIT>' ) <EOL> data = cgi . escape ( data , True ) . replace ( "<STR_LIT:'>" , "<STR_LIT>" ) <EOL> self . body . write ( data ) <EOL> class NOESCAPE ( ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , text ) : <EOL> self . text = text <EOL> def xml ( self ) : <EOL> return self . text <EOL> def render ( content = "<STR_LIT>" , <EOL> stream = None , <EOL> filename = None , <EOL> path = None , <EOL> context = { } , <EOL> lexers = { } , <EOL> delimiters = ( '<STR_LIT>' , '<STR_LIT>' ) , <EOL> writer = '<STR_LIT>' <EOL> ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> from globals import Response <EOL> except ImportError : <EOL> Response = DummyResponse <EOL> if not '<STR_LIT>' in context : <EOL> context [ '<STR_LIT>' ] = NOESCAPE <EOL> if context and '<STR_LIT>' in context : <EOL> old_response_body = context [ '<STR_LIT>' ] . body <EOL> context [ '<STR_LIT>' ] . body = StringIO . StringIO ( ) <EOL> else : <EOL> old_response_body = None <EOL> context [ '<STR_LIT>' ] = Response ( ) <EOL> if not content and not stream and not filename : <EOL> raise SyntaxError ( "<STR_LIT>" ) <EOL> close_stream = False <EOL> if not stream : <EOL> if filename : <EOL> stream = open ( filename , '<STR_LIT:rb>' ) <EOL> close_stream = True <EOL> elif content : <EOL> stream = StringIO . StringIO ( content ) <EOL> code = str ( TemplateParser ( stream . read ( <EOL> ) , context = context , path = path , lexers = lexers , delimiters = delimiters , writer = writer ) ) <EOL> try : <EOL> exec ( code ) in context <EOL> except Exception : <EOL> raise <EOL> if close_stream : <EOL> stream . close ( ) <EOL> text = context [ '<STR_LIT>' ] . body . getvalue ( ) <EOL> if old_response_body is not None : <EOL> context [ '<STR_LIT>' ] . body = old_response_body <EOL> return text <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> import doctest <EOL> doctest . testmod ( ) </s>
