
    Dfh                        d Z ddlZddlZddlZddlZddlZddlmZ ddlZddl	m
Z
 ddlmZmZmZmZ ddlmZ g dZdd	lmZ d
 Z G d d          Z G d d          Z G d d          Z G d d          Z G d d          Z G d d          Z G d d          ZdZ G d d          Z G d de          Z G d d          Z  G d  d!          Z! G d" d#e          Z" G d$ d%e          Z# G d& d'e          Z$ G d( d)e          Z% G d* d+          Z& G d, d-          Z'eee"e$e#e%e d.Z(g d/Z)g d0Z* e+d1 e*D                       Z, G d2 d3          Z- G d4 d5          Z. G d6 d7          Z/ G d8 d9e/          Z0 G d: d;e0          Z1 G d< d=          Z2 G d> d?e2          Z3e2Z4	 dd@l5m6Z6 e3xZ4Z2n# e7$ r Y nw xY wdA Z8dB Z9 G dC dDe:          Z; G dE dFe:          Z<g dGZ= G dH dIej>                  Z? G dJ dKe          Z@dL ZAeBdMk    r6dNejC        v r e9ejC        dO                    dS ddlDZD eDjE                     dS dS )Pa  
simple, elegant templating
(part of web.py)

Template design:

Template string is split into tokens and the tokens are combined into nodes.
Parse tree is a nodelist. TextNode and ExpressionNode are simple nodes and
for-loop, if-loop etc are block nodes, which contain multiple child nodes.

Each node can emit some python string. python string emitted by the
root node is validated for safeeval and executed using python in the given environment.

Enough care is taken to make sure the generated code and the template has line to line match,
so that the error messages can point to exact line number in template. (It doesn't work in some cases still.)

Grammar:

    template -> defwith sections
    defwith -> '$def with (' arguments ')' | ''
    sections -> section*
    section -> block | assignment | line

    assignment -> '$ ' <assignment expression>
    line -> (text|expr)*
    text -> <any characters other than $>
    expr -> '$' pyexpr | '$(' pyexpr ')' | '${' pyexpr '}'
    pyexpr -> <python expression>
    N)open   )websafe)
re_compilesafestrsafeunicodestorage)config)TemplateRenderrenderfrender
ParseErrorSecurityErrortest)MutableMappingc                 f    |                      d          dz   }|r| d|         | |d         fS | dfS )z
    Splits the given text at newline.

        >>> splitline('foo\nbar')
        ('foo\n', 'bar')
        >>> splitline('foo')
        ('foo', '')
        >>> splitline('')
        ('', '')
    
r   N )find)textindexs     ;/var/www/media/lib/python3.11/site-packages/web/template.py	splitliner   9   sD     IIdOOaE FUF|T%&&\))Rx    c                       e Zd ZdZd ZddZd Zd Zd Zd Z	d	 Z
d
 Zd Zd ZddZd Zd Zd Zd Zd ZddZd ZdS )ParserzParser Base.c                 6    t           | _        t          | _        d S N)STATEMENT_NODESstatement_nodesKEYWORDSkeywordsselfs    r   __init__zParser.__init__N   s    . r   
<template>c                     || _         || _        |                     |          \  }}|                     |          }t	          ||          S r   )r   nameread_defwith
read_suiteDefwithNode)r%   r   r)   defwithsuites        r   parsezParser.parseR   sH    		))$//%%7E***r   c                     |                     d          r2t          |          \  }}|dd                                          }||fS d|fS )Nz	$def withr   r   )
startswithr   strip)r%   r   r-   s      r   r*   zParser.read_defwithZ   sQ    ??;'' 	%dOOMGTabbk''))GD= t8Or   c                    |                     d                              d          r|                    d          }|d|         ||dz   d         }}|                     |          }|dk    r|                     |          S || j        v r|                     ||          S || j        v r|                     |          S |	                                dk    r| 
                    |          S |                     |          S )a  Reads one section from the given text.

        section -> block | assignment | line

            >>> read_section = Parser().read_section
            >>> read_section('foo\nbar\n')
            (<line: [t'foo\n']>, 'bar\n')
            >>> read_section('$ a = b + 1\nfoo\n')
            (<assignment: 'a = b + 1'>, 'foo\n')

        read_section('$for in range(10):\n    hello $i\nfoo)
         $Nr   varr   )lstripr1   r   python_lookaheadread_varr!   read_block_sectionr#   read_keywordr2   read_assignmentreadline)r%   r   r   begin_indenttext2aheads         r   read_sectionzParser.read_sectionb   s    ;;s&&s++ 	3JJsOOE"&vv,UQY[[0A%L))%00E~~}}U+++$.....ulCCC$-''((///"$$ ++E222}}T"""r   c                     t          |          \  }}                     |          }t          |          dk     rt          d          |d         }|d         }|                    |d          d                                         }|dk    rn|dk    r|d         dk    r}                     |d	          \  }} fd
|                                D             }g }	|D ]>}
|	                    |
j	                   |	
                    t          d                     ?n                     |          \  }}|j	        }	d |	D             }dd                    |          z  }nt          d          t          ||          |fS )a   Reads a var statement.

        >>> read_var = Parser().read_var
        >>> read_var('var x=10\nfoo')
        (<var: x = 10>, 'foo')
        >>> read_var('var x: hello $name\nfoo')
        (<var: x = join_(u'hello ', escape_(name, True))>, 'foo')
           zInvalid var statementr      =:   r       c                 F    g | ]}                     |          d          S )r   )r=   ).0xr%   s     r   
<listcomp>z#Parser.read_var.<locals>.<listcomp>   s*    IIIq))!,IIIr   c                 8    g | ]}|                     d           S r   emitrJ   nodes     r   rL   z#Parser.read_var.<locals>.<listcomp>   s"    555tTYYr]]555r   z	join_(%s), )r   python_tokenslenSyntaxErrorsplitr2   read_indented_block
splitlinesextendnodesappendTextNoder=   joinVarNode)r%   r   linetokensr)   sepvalueblocklinesr[   rK   linenode_partss   `             r   r9   zParser.read_var   s    t__
d##D))v;;??5666ayQi

3""1%++--#::CZZayD  "66tVDDtIIIIe6F6F6H6HIII 1 1ALL)))LL$00001 #mmE22! 55u555E$))E"2"22EE5666tU##T))r   c                     g }|r/|                      |          \  }}|                    |           |/t          |          S )zReads section by section till end of text.

        >>> read_suite = Parser().read_suite
        >>> read_suite('hello $name\nfoo\n')
        [<line: [t'hello ', $name, t'\n']>, <line: [t'foo\n']>]
        )rA   r\   	SuiteNode)r%   r   sectionssections       r   r+   zParser.read_suite   sT      	% --d33MGTOOG$$$  	% """r   c                     t          |          \  }}|                    d          r
|dd         }g }|r/|                     |          \  }}|                    |           |/t	          |          |fS )a  Reads one line from the text. Newline is suppressed if the line ends with \.

        >>> readline = Parser().readline
        >>> readline('hello $name!\nbye!')
        (<line: [t'hello ', $name, t'!\n']>, 'bye!')
        >>> readline('hello $name!\\\nbye!')
        (<line: [t'hello ', $name, t'!']>, 'bye!')
        >>> readline('$f()\n\n')
        (<line: [$f(), t'\n']>, '\n')
        z\
N)r   endswith	read_noder\   LineNode)r%   r   r`   r[   rR   s        r   r=   zParser.readline   s     t__
d ==   	9D 	--JD$LL  	 $$r   c                    |                     d          rt          d          |dd         fS |                     d          r#t          |          \  }}t          d          |fS |                     d          rE|dd         }|                     d          rd	}|dd         }nd
}|                     ||          S |                     |          S )zReads a node from the given text and returns the node and remaining text.

        >>> read_node = Parser().read_node
        >>> read_node('hello $name')
        (t'hello ', '$name')
        >>> read_node('$name')
        ($name, '')
        $$r5   rD   N$#r   r   rF   FTescape)r1   r]   r   	read_expr	read_text)r%   r   r`   rv   s       r   rp   zParser.read_node   s     ??4   	(C==$qrr(**__T"" 	("4JD$D>>4''__S!! 		(8Ds## ABBx>>$v>666>>$'''r   c                     |                     d          }|dk     rt          |          dfS t          |d|                   ||d         fS )zReads a text node from the given text.

        >>> read_text = Parser().read_text
        >>> read_text('hello $name')
        (t'hello ', '$name')
        r5   r   r   N)r   r]   )r%   r   r   s      r   rx   zParser.read_text   sP     		#199D>>2%%D%L))4<77r   c                 r    t          |          \  }}t          |                                dz             |fS Nr   )r   StatementNoder2   r%   r   r`   s      r   r;   zParser.read_keyword   s1    t__
dTZZ\\D011477r   Tc                 j  	
 	
fd}fd
	fd		
fdfddddd	d
 } G d d          } | ||                                                     j        v r              n
 |             j        j        \  }}t	          |d|         |          ||d         fS )ae  Reads a python expression from the text and returns the expression and remaining text.

        expr -> simple_expr | paren_expr
        simple_expr -> id extended_expr
        extended_expr -> attr_access | paren_expr extended_expr | ''
        attr_access -> dot id extended_expr
        paren_expr -> [ tokens ] | ( tokens ) | { tokens }

            >>> read_expr = Parser().read_expr
            >>> read_expr("name")
            ($name, '')
            >>> read_expr("a.b and c")
            ($a.b, ' and c')
            >>> read_expr("a. b")
            ($a, '. b')
            >>> read_expr("name</h1>")
            ($name, '</h1>')
            >>> read_expr("(limit)ing")
            ($(limit), 'ing')
            >>> read_expr('a[1, 2][:3].f(1+2, "weird string[).", 3 + 4) done.')
            ($a[1, 2][:3].f(1+2, "weird string[).", 3 + 4), ' done.')
        c                  0                                 d S r    )extended_expr
identifiers   r   simple_exprz%Parser.read_expr.<locals>.simple_expr  s    JLLLMOOOOOr   c                  &    t                      d S r   next)ra   s   r   r   z$Parser.read_expr.<locals>.identifier  s    LLLLLr   c                                                       } | d S | j        dk    r              d S | j        v r                            d S d S )N.)	lookaheadrc   )r   attr_accessr   
paren_exprparensra   s    r   r   z'Parser.read_expr.<locals>.extended_expr  sg    ((**I C''F**
r   c                      ddl m}                                  j        | k    r%t	                                                 d S d S )Nr   )NAME)tokenr   
lookahead2typer   )r   r   r   ra   s    r   r   z%Parser.read_expr.<locals>.attr_access   s\    """"""  ""'4//V
 0/r   c                      t                    j        } |          }	                                 j        v r              nt                    }|j        |k    rnBd S r   )r   rc   r   )beginendtr   r   ra   s      r   r   z$Parser.read_expr.<locals>.paren_expr(  sk    LL&E-C##%%+v55JLLLLVAw#~~ Fr   )]})([{c              3   P  K   t          | g          fd}d}t          j        |          D ]v}t          |d         |d         |d         |d                   }|<||j        k    r1|\  }}|j        \  }}t          d| ||         ||j                  V  |j        }|V  wdS )	a:  tokenize text using python tokenizer.
            Python tokenizer ignores spaces, but they might be important in some cases.
            This function introduces dummy space tokens when it identifies any ignored space.
            Each token is a storage object containing type, value, begin and end.
            c                  "    t                     S r   r   is   r   <lambda>z6Parser.read_expr.<locals>.get_tokens.<locals>.<lambda>=  s    tAww r   Nr   r   rD   rG   r   rc   r   r   )itertokenizegenerate_tokensr	   r   r   )r   r=   r   r   rg   x1x2r   s          @r   
get_tokensz$Parser.read_expr.<locals>.get_tokens6  s       dVA&HC-h77  1QqT11Q4HHH?sag~~EArGEAr!rbeCQWUUUUUUe r   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )$Parser.read_expr.<locals>.BetterIterz6Iterator like object with 2 support for 2 look aheads.c                 X    t          |          | _        g | _        d| _        d | _        d S Nr   )r   	iteritemsitemspositioncurrent_itemr%   r   s     r   r&   z-Parser.read_expr.<locals>.BetterIter.__init__K  s+    !%e
 !$(!!!r   c                     t          | j                  | j        k    r,| j                            |                                            | j        | j                 S r   rU   r   r   r\   _nextr$   s    r   r   z.Parser.read_expr.<locals>.BetterIter.lookaheadQ  sD    tz??dm33J%%djjll333z$-00r   c                 N    	 t          | j                  S # t          $ r Y d S w xY wr   )r   r   StopIterationr$   s    r   r   z*Parser.read_expr.<locals>.BetterIter._nextV  s9     ///$      44 s    
$$c                     t          | j                  | j        dz   k    r,| j                            |                                            | j        | j        dz            S Nr   r   r$   s    r   r   z/Parser.read_expr.<locals>.BetterIter.lookahead2\  sN    tz??dma&777J%%djjll333z$-!"344r   c                 b    |                                  | _        | xj        dz  c_        | j        S r   )r   r   r   r$   s    r   __next__z-Parser.read_expr.<locals>.BetterIter.__next__a  s-    $(NN$4$4!"((r   N)	__name__
__module____qualname____doc__r&   r   r   r   r   r   r   r   
BetterIterr   H  se        HH) ) )1 1 1
     5 5 5
) ) ) ) )r   r   Nru   )r   rc   r   r   ExpressionNode)r%   r   rv   r   r   r   rowcolr   r   r   r   r   ra   s           @@@@@@r   rw   zParser.read_expr   s~   0	 	 	 	 	 		 	 	 	 	
	 
	 
	 
	 
	 
	 
	 
	 
		  	  	  	  	  	  	 
	 
	 
	 
	 
	 
	 
	 3//	 	 	$	) 	) 	) 	) 	) 	) 	) 	)< JJt,,--#v--JLLLLKMMM&*Sd4C4j888$stt*DDr   c                 l    t          |          \  }}t          |                                          |fS )zReads assignment statement from text.

        >>> read_assignment = Parser().read_assignment
        >>> read_assignment('a = b + 1\nfoo')
        (<assignment: 'a = b + 1'>, 'foo')
        )r   AssignmentNoder2   r}   s      r   r<   zParser.read_assignmento  s.     t__
ddjjll++T11r   c                     t          |g          fd}t          j        |          }t          |          d         S )a   Returns the first python token from the given text.

        >>> python_lookahead = Parser().python_lookahead
        >>> python_lookahead('for i in range(10):')
        'for'
        >>> python_lookahead('else:')
        'else'
        >>> python_lookahead(' x = 1')
        ' '
        c                  "    t                     S r   r   r   s   r   r   z)Parser.python_lookahead.<locals>.<lambda>      477 r   r   )r   r   r   r   r%   r   r=   ra   r   s       @r   r8   zParser.python_lookaheady  s=     $LL"???)(33F||Ar   c                 n    t          |g          fd}t          j        |          }d |D             S )Nc                  "    t                     S r   r   r   s   r   r   z&Parser.python_tokens.<locals>.<lambda>  r   r   c                     g | ]
}|d          S )r   r   )rJ   r   s     r   rL   z(Parser.python_tokens.<locals>.<listcomp>  s    %%%!%%%r   )r   r   r   r   s       @r   rT   zParser.python_tokens  s?    $LL"???)(33%%f%%%%r   c                     |dk    rd|fS d}|ret          |          \  }}|                                dk    r|dz  }n1|                    |          r||t          |          d         z  }nn|}|e||fS )a   Read a block of text. A block is what typically follows a for or it statement.
        It can be in the same line as that of the statement or an indented block.

            >>> read_indented_block = Parser().read_indented_block
            >>> read_indented_block('  a\n  b\nc', '  ')
            ('a\nb\n', 'c')
            >>> read_indented_block('  a\n    b\n  c\nd', '  ')
            ('a\n  b\nc\n', 'd')
            >>> read_indented_block('  a\n\n    b\nc', '  ')
            ('a\n\n  b\n', 'c')
        r   r   N)r   r2   r1   rU   )r%   r   indentrd   r`   r?   s         r   rX   zParser.read_indented_block  s     R<<t8O 	#D//KD%zz||r!!(( c&kkmm,,D  	 d{r   c                     t          |          }|                    d           |d|j                 ||j        d         fS )zReads a python statement.

        >>> read_statement = Parser().read_statement
        >>> read_statement('for i in range(10): hello $name')
        ('for i in range(10):', ' hello $name')
        rF   N)PythonTokenizerconsume_tillr   )r%   r   toks      r   read_statementzParser.read_statement  sF     d##KciK $sy{{"333r   r   c                    t          |          \  }}|                     |          \  }}|                     |          }|                                r<|                                                    d          s|                                }n`d } ||          t          |          d         }|dk    r||z   }	n|t          |t                    z   }	| 	                    ||	          \  }}| 
                    ||||          |fS )a  
            >>> read_block_section = Parser().read_block_section
            >>> read_block_section('for i in range(10): hello $i\nfoo')
            (<block: 'for i in range(10):', [<line: [t'hello ', $i, t'\n']>]>, 'foo')
            >>> read_block_section('for i in range(10):\n        hello $i\n    foo', begin_indent='    ')
            (<block: 'for i in range(10):', [<line: [t'hello ', $i, t'\n']>]>, '    foo')
            >>> read_block_section('for i in range(10):\n  hello $i\nfoo')
            (<block: 'for i in range(10):', [<line: [t'hello ', $i, t'\n']>]>, 'foo')

        With inline comment:

            >>> read_block_section('for i in range(10):  $# inline comment\n hello $i\nfoo')
            (<block: 'for i in range(10):', []>, ' hello $i\nfoo')
        rt   c                     t          d          }|                    |           }|o|                    d          }|pdS )Nz  +r   r   )r   matchgroup)r   rxr   first_indents       r   find_indentz.Parser.read_block_section.<locals>.find_indent  s=    &&$7Q#)r)r   Ncode)r   r   r8   r2   r7   r1   rU   minINDENTrX   create_block_node)
r%   r   r>   r`   stmtkeywordrd   r   r   r   s
             r   r:   zParser.read_block_section  s    t__
d((..
d''-- ::<< 	A 8 8 > > 	AKKMMEE* * * ';t,,S->->-@-@AL &  %4%L&(A(AA224@@KE4%%gtULII4OOr   c                     || j         v r | j         |         |||          S t          dt          |          z            )NzUnknown statement: %s)r!   r   repr)r%   r   r   rd   r>   s        r   r   zParser.create_block_node  sF    d***04'0ulKKK4tG}}DEEEr   N)r'   TrN   )r   r   r   r   r&   r/   r*   rA   r9   r+   r=   rp   rx   r;   rw   r<   r8   rT   rX   r   r:   r   r   r   r   r   r   K   sK       ! ! !+ + + +  # # #<$* $* $*L# # #% % %0( ( (28 8 88 8 8xE xE xE xEt2 2 2   & & &  6	4 	4 	4)P )P )P )PVF F F F Fr   r   c                   $    e Zd ZdZd Zd Zd ZdS )r   z&Utility wrapper over python tokenizer.c                     || _         t          |g          fd}t          j        |          | _        d| _        d S )Nc                  "    t                     S r   r   r   s   r   r   z*PythonTokenizer.__init__.<locals>.<lambda>  r   r   r   )r   r   r   r   ra   r   )r%   r   r=   r   s      @r   r&   zPythonTokenizer.__init__  s?    	$LL"???.x88


r   c                 .   	 	 t          |           }|j        |k    rd	S |j        dk    r|                     d           nA|j        dk    r|                     d           n |j        dk    r|                     d           |j        dk    rd	S #  Y d	S xY w)
zConsumes tokens till colon.

        >>> tok = PythonTokenizer('for i in range(10): hello $i')
        >>> tok.consume_till(':')
        >>> tok.text[:tok.index]
        'for i in range(10):'
        >>> tok.text[tok.index:]
        ' hello $i'
        Tr   r   r   r   r   r   r   N)r   rc   r   )r%   delimr   s      r   r   zPythonTokenizer.consume_till  s    	JJ7e##EW^^%%c****W^^%%c****W^^%%c*** 7d??E!"	
 FFs   B A-B B Bc                 t    t          | j                  \  }}}}}|\  }}|| _        t          ||||          S )Nr   )r   ra   r   r	   )r%   r   r   r   r   r`   r   r   s           r   r   zPythonTokenizer.__next__  sC    $($5$5!aTS
DC@@@@r   N)r   r   r   r   r&   r   r   r   r   r   r   r     sM        00  ! ! !FA A A A Ar   r   c                        e Zd Zd Zd Zd ZdS )r,   c                     |r/|                     dd          dz   | _        | xj        dz  c_        nd| _        | xj        dz  c_        | xj        dz  c_        | xj        dz  c_        || _        d	| _        d S )
Nwith__template__rF   z
    __lineoffset__ = -4zdef __template__():z
    __lineoffset__ = -5z
    loop = ForLoop()z3
    self = TemplateResult(); extend_ = self.extendz
    return self)replacer-   r.   r   )r%   r-   r.   s      r   r&   zDefwithNode.__init__  s     	8"??6>BBSHDLLL77LLL0DLLL77LL00NN
&r   c                 p    d}|| j         z   | j                            |t          z             z   | j        z   S )Nz# coding: utf-8
)r-   r.   rP   r   r   )r%   r   encodings      r   rP   zDefwithNode.emit+  s2    &$,&&)I)IIDHTTr   c                 (    d| j         d| j        dS )Nz
<defwith: rS   >)r-   r.   r$   s    r   __repr__zDefwithNode.__repr__/  s     &*lllDJJJ??r   Nr   r   r   r&   rP   r   r   r   r   r,   r,     sI        ' ' 'U U U@ @ @ @ @r   r,   c                   "    e Zd Zd ZddZd ZdS )r]   c                     || _         d S r   )rc   )r%   rc   s     r   r&   zTextNode.__init__4      


r   r   c                 D    t          t          | j                            S r   )r   r   rc   r%   r   r>   s      r   rP   zTextNode.emit7  s    K
++,,,r   c                 0    dt          | j                  z   S )Nr   )r   rc   r$   s    r   r   zTextNode.__repr__:  s    T$*%%%%r   NrN   r   r   r   r   r]   r]   3  sF          - - - -& & & & &r   r]   c                   $    e Zd ZddZddZd ZdS )	r   Tc                     |                                 | _        |                    d          r/|                    d          rd| j        dd         z   dz   | _        || _        d S )Nr   r   r   r   r   r   )r2   rc   r1   ro   rv   r%   rc   rv   s      r   r&   zExpressionNode.__init__?  sc    [[]]
 C   	6U^^C%8%8 	6tz!B$//#5DJr   r   c                 B    d| j         dt          | j                  dS )Nzescape_(rS   r   )rc   boolrv   r   s      r   rP   zExpressionNode.emitH  s%     $(JJJT[0A0A0A0ABBr   c                 2    | j         rd}nd}d|| j        S )Nr   rF   r5   )rv   rc   )r%   rv   s     r   r   zExpressionNode.__repr__K  s*    ; 	FFF &$**--r   Nr   rN   r   r   r   r   r   r   >  sO           C C C C. . . . .r   r   c                   "    e Zd Zd ZddZd ZdS )r   c                     || _         d S r   r   )r%   r   s     r   r&   zAssignmentNode.__init__T      			r   r   c                     || j         z   dz   S r{   r  r   s      r   rP   zAssignmentNode.emitW  s    	!D((r   c                 0    dt          | j                  z  S )Nz<assignment: %s>r   r   r$   s    r   r   zAssignmentNode.__repr__Z  s    !DOO33r   NrN   r   r   r   r   r   r   S  sF          ) ) ) )4 4 4 4 4r   r   c                   "    e Zd Zd ZddZd ZdS )rq   c                     || _         d S r   )r[   )r%   r[   s     r   r&   zLineNode.__init___  r   r   r   c                     d | j         D             }|rt          |          g|z   }|dd                    |          z  z   S )Nc                 8    g | ]}|                     d           S rN   rO   rQ   s     r   rL   z!LineNode.emit.<locals>.<listcomp>c  s"    555$		"555r   zextend_([%s])
rS   )r[   r   r^   )r%   r   text_indentr)   r   s        r   rP   zLineNode.emitb  sO    55$*555 	.%%&-D)DIIdOO;;;r   c                 0    dt          | j                  z  S )Nz
<line: %s>)r   r[   r$   s    r   r   zLineNode.__repr__i  s    d4:....r   N)r   r   r   r   r   r   rq   rq   ^  sF          < < < </ / / / /r   rq   rH   c                   $    e Zd ZddZddZd ZdS )	BlockNoder   c                 n    || _         t                                          |          | _        || _        d S r   )r   r   r+   r.   r>   r%   r   rd   r>   s       r   r&   zBlockNode.__init__q  s0    	XX((//
(r   c                 v    | j         |z   }|| j        z   | j                            |t          z   |          z   }|S r   r>   r   r.   rP   r   r%   r   r  outs       r   rP   zBlockNode.emitv  s9    '+5ty 4:??6F?K#P#PP
r   c                 \    dt          | j                  dt          | j                  dS Nz<block: rS   r   )r   r   r.   r$   s    r   r   zBlockNode.__repr__{  s+     $(OOOOT$*5E5E5E5EFFr   NrN   r   r   r   r   r  r  p  sP        ) ) ) )
   
G G G G Gr   r  c                       e Zd ZddZd ZdS )ForNoder   c                    || _         t          |          }|                    d           |d |j                 }||j        d         }|dz   |                                z   dz   }t
                              | |||           d S )Ninr   z loop.setup(z):)original_stmtr   r   r   r2   r  r&   )r%   r   rd   r>   r   abs          r   r&   zForNode.__init__  s    !d##39R >!AGGII-44ul;;;;;r   c                 \    dt          | j                  dt          | j                  dS r  )r   r  r.   r$   s    r   r   zForNode.__repr__  s0     $();$<$<$<$<d4:>N>N>N>NOOr   NrN   )r   r   r   r&   r   r   r   r   r  r    s<        < < < <P P P P Pr   r  c                   $    e Zd ZddZddZd ZdS )CodeNoder   c                     d|z   | _         d S r{   r  r  s       r   r&   zCodeNode.__init__  s    5L			r   c                     dd l }|                    d|j                  }|                    || j                                      d          S )Nr   ^r4   )recompileMsubr   rstrip)r%   r   r  r$  r   s        r   rP   zCodeNode.emit  sD    			ZZRT""vvfdi((//444r   c                 0    dt          | j                  z  S )Nz
<code: %s>r  r$   s    r   r   zCodeNode.__repr__      d49oo--r   NrN   r   r   r   r   r   r     sK        ! ! ! !5 5 5 5. . . . .r   r   c                   "    e Zd Zd ZddZd ZdS )r|   c                     || _         d S r   r   )r%   r   s     r   r&   zStatementNode.__init__  r  r   r   c                     || j         z   S r   r-  r   s      r   rP   zStatementNode.emit  s    	!!r   c                 0    dt          | j                  z  S )Nz
<stmt: %s>)r   r   r$   s    r   r   zStatementNode.__repr__  r*  r   NrN   r   r   r   r   r|   r|     sF          " " " ". . . . .r   r|   c                       e Zd ZdS )IfNodeNr   r   r   r   r   r   r1  r1            Dr   r1  c                       e Zd ZdS )ElseNodeNr2  r   r   r   r5  r5    r3  r   r5  c                       e Zd ZdS )ElifNodeNr2  r   r   r   r7  r7    r3  r   r7  c                       e Zd Zd ZddZdS )DefNodec                 
   t          j        | g|R i | t          dd          }d|_        | j        j                            d|           t          dd          }d|_        | j        j                            |           d S )Nr   z/self = TemplateResult(); extend_ = self.extend
r   zreturn self
)r  r&   r   r   r.   rk   insertr\   )r%   r  kwr   s       r   r&   zDefNode.__init__  s    4*!***r***BF	
""1d+++B#	
""4(((((r   r   c                     | j         |z   }|| j        z   | j                            |t          z   |          z   }|dz   |z   S )Nz__lineoffset__ -= 3
r  r  s       r   rP   zDefNode.emit  sE    '+5ty 4:??6F?K#P#PP//#55r   NrN   )r   r   r   r&   rP   r   r   r   r9  r9    s7        	) 	) 	)6 6 6 6 6 6r   r9  c                        e Zd Zd Zd Zd ZdS )r_   c                 "    || _         || _        d S r   r)   rc   r%   r)   rc   s      r   r&   zVarNode.__init__  s    	


r   c                 H    |dt          | j                  d| j        dz   S )Nzself[z] = r   )r   r)   rc   r%   r   r  s      r   rP   zVarNode.emit  s&    vT$)____djjjIIIr   c                 (    d| j         d| j        dS )Nz<var: z = r   r@  r$   s    r   r   zVarNode.__repr__  s     #'999djjj99r   Nr   r   r   r   r_   r_     sD          J J J: : : : :r   r_   c                   &    e Zd ZdZd ZddZd ZdS )rj   zSuite is a list of sections.c                     || _         d S r   )rk   )r%   rk   s     r   r&   zSuiteNode.__init__  s     r   r   c                 Z    dd                     fd| j        D                       z   S )Nr   r   c                 <    g | ]}|                               S r   rO   )rJ   sr   r  s     r   rL   z"SuiteNode.emit.<locals>.<listcomp>  s'    RRRqqvvfk::RRRr   )r^   rk   rC  s    ``r   rP   zSuiteNode.emit  s5    bggRRRRRDMRRRSSSSr   c                 *    t          | j                  S r   )r   rk   r$   s    r   r   zSuiteNode.__repr__  s    DM"""r   NrN   )r   r   r   r   r&   rP   r   r   r   r   rj   rj     sP        &&! ! !T T T T# # # # #r   rj   )forwhileifelifelsedefr   )passbreakcontinuereturn)#dict	enumeratefloatintr   listlongreversedsetslicetuplexrangeabsallanycallablechrcmpdivmodfilterhexid
isinstancer   rU   maxr   octordpowrangeTrueFalseNone
__import__c                 X    g | ]'}|t           j        v |t          t           |          f(S r   )builtins__dict__getattr)rJ   r)   s     r   rL   rL     s?       8$$$ 
wx&&'$$$r   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )ForLoopa  
    Wrapper for expression in for stament to support loop.xxx helpers.

        >>> loop = ForLoop()
        >>> for x in loop.setup(['a', 'b', 'c']):
        ...     print(loop.index, loop.revindex, loop.parity, x)
        ...
        1 3 odd a
        2 2 even b
        3 1 odd c
        >>> loop.index
        Traceback (most recent call last):
            ...
        AttributeError: index
    c                     d | _         d S r   )_ctxr$   s    r   r&   zForLoop.__init__*  r  r   c                 X    | j         t          |          t          | j         |          S r   )r{  AttributeErrorrw  r%   r)   s     r   __getattr__zForLoop.__getattr__-  s*    9 &&&49d+++r   c                 ^    |                                   | j                            |          S r   )_pushr{  setup)r%   seqs     r   r  zForLoop.setup3  s#    

ys###r   c                 :    t          | | j                  | _        d S r   )ForLoopContextr{  r$   s    r   r  zForLoop._push7  s    "433			r   c                 (    | j         j        | _         d S r   )r{  parentr$   s    r   _popzForLoop._pop:  s    I$			r   N)	r   r   r   r   r&   r  r  r  r  r   r   r   ry  ry    si            , , ,$ $ $4 4 4% % % % %r   ry  c                       e Zd ZdZd Zd Z ed           Z ed           Z ed           Z	 ed           Z
 ed           Z ed	           Z ed
           Z ed           ZdS )r  z:Stackable context for ForLoop to support nested for loops.c                 "    || _         || _        d S r   )_forloopr  )r%   forloopr  s      r   r&   zForLoopContext.__init__A  s    r   c              #      K   	 t          |          | _        n#  d| _        Y nxY wd| _        |D ]}| xj        dz  c_        |V  | j                                         d S )Nr   r   )rU   lengthr   r  r  )r%   r  r  s      r   r  zForLoopContext.setupE  sx      	c((DKK	DKKK
 	 	AJJ!OJJGGGGs    	$c                     | j         dz
  S r   r   r$   s    r   r   zForLoopContext.<lambda>Q  s    4:> r   c                     | j         dk    S r   r  r$   s    r   r   zForLoopContext.<lambda>R  s    $*/ r   c                 "    | j         | j        k    S r   )r   r  r$   s    r   r   zForLoopContext.<lambda>S  s    t{!: r   c                     | j         dz  dk    S )NrD   r   r  r$   s    r   r   zForLoopContext.<lambda>T  s    
Q! 3 r   c                     | j         dz  dk    S )NrD   r   r  r$   s    r   r   zForLoopContext.<lambda>U  s    a1!4 r   c                      ddg| j                  S )Noddeven)r  r$   s    r   r   zForLoopContext.<lambda>V  s    E6?49#= r   c                      | j         | j        z
  S r   r  r   r$   s    r   r   zForLoopContext.<lambda>W  s    dkDJ&> r   c                 &    | j         | j        z
  dz   S r   r  r$   s    r   r   zForLoopContext.<lambda>X  s    T[4:%=%A r   N)r   r   r   r   r&   r  propertyindex0firstlastr  r  parity	revindex0revindexr   r   r   r  r  >  s        DD  
 
 
 X1122FH1122E8::;;D
(33
4
4C84455DX==>>F>>??IxAABBHHHr   r  c                   4    e Zd Zd Zd Zd Zd Zd Zd	dZdS )
BaseTemplatec                     || _         || _        || _        || _        |r|                     |          | _        d S d | _        d S )Nc                      dS Nr   r   r   r   r   r   z'BaseTemplate.__init__.<locals>.<lambda>d  s    R r   )filenamerg  _globals	_builtins_compiler   )r%   r   r  rg  globalsru  s         r   r&   zBaseTemplate.__init__\  sJ     ! 	 ]]4((DFFFZDFFFr   c                 v    |                      | j        pi | j                  }t          ||           |d         S )Nr   )make_envr  r  exec)r%   r   envs      r   r  zBaseTemplate._compilef  s6    mmDM/R@@T3>""r   c                      d} | j         |i |S )NT)r   )r%   r  r<  __hidetraceback__s       r   __call__zBaseTemplate.__call__l  s     tvqBr   c                 T    t          ||t          t          | j        | j                  S )N)__builtins__ry  TemplateResultescape_join_)rU  ry  r  _escape_join)r%   r  ru  s      r   r  zBaseTemplate.make_envp  s/    !)L*
 
 
 	
r   c                 ,    d                     |          S r  )r^   r   s     r   r  zBaseTemplate._joinz  s    xxr   Fc                 h    |d}t          |          }|r| j        r|                     |          }|S r  )r   rg  r   s      r   r  zBaseTemplate._escape}  s@    =EE"" 	'dk 	'KK&&Er   N)F)	r   r   r   r&   r  r  r  r  r  r   r   r   r  r  [  ss             # # #     
 
 
       r   r  c                       e Zd ZddddZeeedZi Z	 	 	 	 	 ddZd	 Zd
 Z	 e
e	          Z	d ZddZ e
e          Zd Zd ZdS )r   ztext/html; charset=utf-8z$application/xhtml+xml; charset=utf-8z
text/plain).html.xhtmlz.txt)r  r  z.xmlr'   Nc                    |pg | _         t                              |          }|                     ||          }t          j                            |          \  }}	|p| j                            |	d           }| j	                            |	d           | _
        || j        }|t          }t                              | |||||           d S )N)r   r  rg  r  ru  )
extensionsr   normalize_textcompile_templateospathsplitextFILTERSgetCONTENT_TYPEScontent_typer  TEMPLATE_BUILTINSr  r&   )
r%   r   r  rg  r  ru  r  r   rg   exts
             r   r&   zTemplate.__init__  s     %*&&t,,$$T844!!(++364<++C66 .223==?lG(H 	 	
 	
 	
 	
 	
r   c                 L    d                     | j        j        | j                  S )z{
        >>> Template(text='Template text', filename='burndown_chart.html')
        <Template burndown_chart.html>
        z<{} {}>)format	__class__r   r  r$   s    r   r   zTemplate.__repr__  s!    
  7GGGr   c                 d   |                      dd                               dd                                          } |                     d          s| dz  } d}t          | t                    r,|                     |          r| t          |          d         } |                      dd          } | S )z>Normalizes template text by correcting 
, tabs and BOM chars.z
r   u   ï»¿Nz\$rs   )r   
expandtabsro   rj  strr1   rU   )r   BOMs     r   r  zTemplate.normalize_text  s    ||FD))11$==HHJJ}}T"" 	DLD dC   	$T__S%9%9 	$C

#D ||E4((r   c                     d}ddl m} d|j        v r$| j        r|                    d| j        d           t          j        | g|R i |S )NTr   )webapiheaderszContent-Type)unique)r   r  ctxr  headerr  r  )r%   r  r<  r  webs        r   r  zTemplate.__call__  sk     ######D$5JJ~t'8JFFF$T4A444444r   c                     |pt                      }|                    | |          }|                    d                                          }t	          |          S )Nr   )r   )r   r/   rP   r2   r   )r   r  parserrootnoder   s        r   generate_codezTemplate.generate_code  sP    #688<<h// }}B}''--//t}}r   c                 L    t                      }| j        D ]} ||          }|S r   )r   r  )r%   pr  s      r   create_parserzTemplate.create_parser  s0    HH? 	 	CAAAr   c                    t                               |||                                           }d }	 t          ||d          }nZ# t          $ rM}|xj        dt          |j                  d|j        d ||j        |j        dz
            z  c_         d }~ww xY wt          j
        ||          }t                                          ||           |S )N)r  c                     	 t          | d                                                                          }||         S #  Y d S xY w)Nutf-8r   )r   readrY   )r  linenore   s      r   get_source_linez2Template.compile_template.<locals>.get_source_line  sK    X888==??JJLLV}$tts	   <? Ar  z

Template traceback:
    File z, line z	
        r   )r   r  r  r%  rV   msgr   r  r  astr/   SafeVisitorwalk)r%   template_stringr  r   r  compiled_codeerrast_nodes           r   r  zTemplate.compile_template  s    %%Xd.@.@.B.B & 
 
	 	 		#D(F;;MM 	 	 	GGGS\""""


cj1n=== GG 	 9T8,,8X...s   A 
BABB)r'   NNNNr   )r   r   r   r  r   r  r  r&   r   r  staticmethodr  r  r  r  r   r   r   r   r     s        +8 M
  7GDDGG
 
 
 
 
>H H H   "\.11N5 5 5    !L//M      r   r   c                        e Zd Zd Zd Zd ZdS )CompiledTemplatec                 L    t                               | d|           || _        d S r  )r   r&   r   )r%   fr  s      r   r&   zCompiledTemplate.__init__  s%    $H---r   c                     d S r   r   r%   r  s     r   r  z!CompiledTemplate.compile_template      tr   c                     d S r   r   r  s     r   r  zCompiledTemplate._compile	  r  r   N)r   r   r   r&   r  r  r   r   r   r  r    sA                r   r  c                   @    e Zd ZdZddZddZd Zd Zd Zd	 Z	d
 Z
dS )r   a1  The most preferred way of using templates.

        render = web.template.render('templates')
        print render.foo()

    Optional parameter can be `base` can be used to pass output of
    every template through the base template.

        render = web.template.render('templates', base='layout')
    	templatesNc                      | _         | _        |t          j        dd           }|ri  _        nd  _        rt          d          s fd _        d S  _        d S )NdebugFr  c                 @                                    |           S r   )	_template)pagebaser%   s    r   r   z!Render.__init__.<locals>.<lambda>'  s    &:dnnT&:&:4&@&@ r   )_loc	_keywordsr
   r  _cachehasattr_base)r%   loccacher  r#   s   `  ` r   r&   zRender.__init__  s~    	!=
7E222E 	DKKDK 	j11 	@@@@@DJJJDJJJr   c                 ^    d| j         vr
i | j         d<   |s|j        }|| j         d         |<   dS )z(Add a global to this rendering instance.r  N)r  r   )r%   objr)   s      r   _add_globalzRender._add_global+  sA    DN**(*DN9% 	 <D*-y!$'''r   c                     t           j                            | j        |          }t           j                            |          rd|fS |                     |          }|rd|fS dS )Ndirfile)noneN)r  r  r^   r  isdir	_findfile)r%   r)   r  s      r   _lookupzRender._lookup3  sa    w||DIt,,7== 	$$;>>$''D $t|##|r   c                 R   |                      |          \  }}|dk    r!t          |f| j        d u| j        d| j        S |dk    rQt          |d          5 }t          |                                fd|i| j        cd d d            S # 1 swxY w Y   d S t          d|z             )Nr  r  r  r  r  r  r  zNo template named )	r  r   r  r  r  r   r   r  r}  )r%   r)   kindr  	tmpl_files        r   _load_templatezRender._load_template>  s#   \\$''
d5== Kt3$* HL   V^^dW--- S	 0 0RR4R4>RRS S S S S S S S S S S S S S S S S S !!5!<===s   &B

BBc                     d t          j         |dz             D             }|                                 |s"t          j                            |          r|g}|o|d         S )Nc                 <    g | ]}|                     d           |S )~)ro   rJ   r  s     r   rL   z$Render._findfile.<locals>.<listcomp>L  s7     
 
 
AJJsOO

 
 
r   z.*r   )globsortr  r  exists)r%   path_prefixr  s      r   r  zRender._findfileK  sr    
 
yt!344
 
 
 	
  	RW^^K00 	AzQqTr   c                     | j         3|| j         vr|                     |          | j         |<   | j         |         S |                     |          S r   )r  r  r~  s     r   r  zRender._templateX  sR    ;"4;&&$($7$7$=$=D!;t$$&&t,,,r   c                                            |           j        rt          t                    r fd}|S                       |          S )Nc                  :                          | i |          S r   )r  )r  r<  r%   r   s     r   templatez$Render.__getattr__.<locals>.templated  s!    zz!!Q+"++...r   )r  r  rj  r   )r%   r)   r#  r   s   `  @r   r  zRender.__getattr__`  sg    NN4  : 	(*Q11 	(/ / / / / / O>>$'''r   )r  NNr   )r   r   r   r   r&   r  r  r  r  r  r  r   r   r   r   r     s        	 	   $. . . .	$ 	$ 	$> > >  - - -	( 	( 	( 	( 	(r   r   c                       e Zd ZeZd Zd ZdS )
GAE_Renderc                 (   t          j        j        | |g|R i | dd l}t	          ||j                  r|| _        nA|                    d                              dd          }t          |d d dg          | _        | j        j
                            |                    dt                               | j        j
                            t          j                   | j        j
                            |                    di                      d S )Nr   /r   rK   ru  r  )r%  superr&   typesrj  
ModuleTypemodr(  r   rs  rv  updater  r  r   r  )r%   r  r  r<  r)  r)   s         r   r&   zGAE_Render.__init__p  s    !$6a6662666c5+,, 	;DHH::c??**344D!$dSE::DH  
4E!F!FGGG  !1222  	2!6!677777r   c                     t          | j        |          }dd l}t          ||j                  r!t          |f| j        d u| j        d| j        S |S )Nr   r  )	rw  r+  r)  rj  r*  r%  r  r  r  )r%   r)   r   r)  s       r   r  zGAE_Render._load_template  so    DHd##a)** 	D0tz EI^   Hr   N)r   r   r   r   r(  r&   r  r   r   r   r%  r%  l  s7        E8 8 8	 	 	 	 	r   r%  )	appenginec                 b    t          t          | d                                          fd| i|S )z,Creates a template from the given file path.r  r  r  )r   r   r  )r  r#   s     r   r   r     s6    D0005577SS$S(SSSr   c                    t          j        |           D ]=\  }}}d |D             }|dd         D ],}|                    d          r|                    |           -t	          t           j                            |d          dd          }|                    d           |r+|                    d	d
                    |          z              |                    d           |D ]T}t           j                            ||          }d|v r|                    dd          \  }}	n|}t	          |d          	                                }
t                              |
          }
t                              |
|          }|                    d|d          }|                    |           |                    d           |                    |d|d
t          |          d           |                    d|d|d           t          t	          |d          	                                |           V|                                 ?dS )z"Compiles templates to python code.c                     g | ]C}|                     d           |                    d          ,|                     d          A|DS )r   r  __init__.py)r1   ro   r  s     r   rL   z%compile_templates.<locals>.<listcomp>  sd     
 
 
<<$$
 JJsOO	

 LL//

 
 
r   Nr   r2  wr  r  zDfrom web.template import CompiledTemplate, ForLoop, TemplateResult

zimport rS   r   r   r   z

z = CompiledTemplate(z)
zjoin_ = z._join; escape_ = z
._escape

)r  r  r1   remover   r  r^   writerW   r  r   r  r  r   r   close)rootdirpathdirnames	filenamesdr  r  r  r)   rg   r   r   s               r   compile_templatesr<    sR   (* + +$9
 

 
 
	 !!! 	# 	#A||C   #"""27<<77wOOO		T	
 	
 	
  	7IIi$))H"5"55666		$ 	@ 	@A7<<++Daxx''#q//aaw///4466D**400D))$55D<<a88DIIdOOOIIfII444tDzzzzRSSSIIIdddDDDQRRR T$1116688$????		W+ +r   c                       e Zd ZdS )r   Nr2  r   r   r   r   r     r3  r   r   c                       e Zd ZdZdS )r   z8The template seems to be trying to do something naughty.N)r   r   r   r   r   r   r   r   r     s        BBDr   r   )VAddAndAssign	Attribute	AugAssignAugLoadAugStoreBinOpBitAndBitOrBitXorBoolOpBreakCallClassDefCompareConstantContinueDelDeleteDictDictCompDivEllipsisEqExceptHandlerExpr
ExpressionExtSliceFloorDivForFunctionDefGeneratorExpGtGtEIfIfExpInIndexInteractiveInvertIsIsNot	JoinedStrLShiftLambdaListListCompLoadLtLtEModModuleMultNameNameConstantNotNotEqNotInNumOrParamPassPowRShiftReturnSetSetCompSliceStoreStrSub	SubscriptSuiteTupleUAddUSubUnaryOpWhileWithYieldaliasarg	argumentscomprehensionr   c                   v     e Zd ZdZ fdZd Z fdZ fdZd Zd Z	 fdZ
d	 Zd
 Zd Zd Zd Zd Z xZS )r  a  
    Make sure code is safe by walking through the AST.

    Code considered unsafe if:
        * it has restricted AST nodes (only nodes defined in ALLOWED_AST_NODES are allowed)
        * it is trying to assign to attributes
        * it is trying to access resricted attributes

    Adopted from http://www.zafar.se/bkz/uploads/safe.txt (public domain, Babar K. Zafar)
        * Using ast rather than compiler tree, for jython and Py3 support since Py2.6
        * Simplified with ast.NodeVisitor class
    c                 V     t          t          |           j        |i | g | _        dS )zBInitialize visitor by generating callbacks for all AST node types.N)r(  r  r&   errors)r%   argskwargsr  s      r   r&   zSafeVisitor.__init__=  s0    )k4  )4:6:::r   c                     || _         |                     |           | j        r1t          d                    d | j        D                                 dS )zJValidate each node in AST and raise SecurityError if the code is not safe.r   c                 ,    g | ]}t          |          S r   )r  )rJ   r  s     r   rL   z$SafeVisitor.walk.<locals>.<listcomp>G  s    *K*K*K3s88*K*K*Kr   N)r  visitr  r   r^   )r%   treer  s      r   r  zSafeVisitor.walkB  s]     

4; 	N		*K*Kt{*K*K*K L LMMM	N 	Nr   c                     t          |          j        }|t          vr|                     ||           t	          t
          |                               |           d S r   )r   r   ALLOWED_AST_NODES	fail_namer(  r  generic_visit)r%   rR   nodenamer  s      r   r  zSafeVisitor.generic_visitI  sU    ::&,,,NN4***k4  ..t44444r   c                     |                      |          }|                     |          r|                     ||           t          t          |                               |           d S r   )get_node_attris_unallowed_attrfail_attributer(  r  r  )r%   rR   attrnamer  s      r   visit_AttributezSafeVisitor.visit_AttributeO  sf    %%d++!!(++ 	0h///k4  ..t44444r   c                 0    |                      |           d S r   )check_assign_targetsr%   rR   s     r   visit_AssignzSafeVisitor.visit_AssignU  s    !!$'''''r   c                 0    |                      |           d S r   )check_assign_targetr  s     r   visit_AugAssignzSafeVisitor.visit_AugAssignX  s      &&&&&r   c                     |j         D ]}|                     |           t          t          |                               |           d S r   )targetsr  r(  r  r  )r%   rR   targetr  s      r   r  z SafeVisitor.check_assign_targets[  sO    l 	- 	-F$$V,,,,k4  ..t44444r   c                     t          |          j        }|dk    r-|                     |          }|                     ||           d S d S )NrB  )r   r   r  r  )r%   
targetnode
targetnamer  s       r   r  zSafeVisitor.check_assign_target`  sT    *%%.
$$))*55H
H55555 %$r   c                     |                      |          }t          d| j        ||fz            }| j                            |           d S )Nz.%s:%d - execution of '%s' statements is deniedget_node_linenor   r  r  r\   )r%   rR   r  r  es        r   r  zSafeVisitor.fail_nameg  sV    %%d++<}fh/0
 
 	1r   c                     |                      |          }t          d| j        ||fz            }| j                            |           d S )Nz*%s:%d - access to attribute '%s' is deniedr  )r%   rR   r  r  r  s        r   r  zSafeVisitor.fail_attributeo  sV    %%d++8}fh/0
 
 	1r   c                     |                     d          p)|                     d          p|                     d          S )Nrg   func_im_)r1   r~  s     r   r  zSafeVisitor.is_unallowed_attrx  s9    OOC  VDOOG$<$<VPU@V@V	
r   c                 &    d|j         v r|j        pd S )Nattr)_fieldsr  r  s     r   r  zSafeVisitor.get_node_attr}  s    %3$);t;r   c                 "    |j         r|j         pdS r   )r  r  s     r   r  zSafeVisitor.get_node_lineno  s    ,11r   )r   r   r   r   r&   r  r  r  r  r  r  r  r  r  r  r  r  __classcell__)r  s   @r   r  r  /  s            
N N N5 5 5 5 55 5 5 5 5( ( (' ' '5 5 5 5 5
6 6 6    
 
 

< < <2 2 2 2 2 2 2r   r  c                   f    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd ZdS )r  a  Dictionary like object for storing template output.

    The result of a template execution is usually a string, but sometimes it
    contains attributes set using $var. This class provides a simple
    dictionary like interface for storing the output of the template and the
    attributes. The output is stored with a special key __body__. Converting
    the TemplateResult to string or unicode returns the value of __body__.

    When the template is in execution, the output is generated part by part
    and those parts are combined at the end. Parts are added to the
    TemplateResult by calling the `extend` method and the parts are combined
    seamlessly when __body__ is accessed.

        >>> d = TemplateResult(__body__='hello, world', x='foo')
        >>> print(d)
        hello, world
        >>> d.x
        'foo'
        >>> d = TemplateResult()
        >>> d.extend([u'hello', u'world'])
        >>> d
        <TemplateResult: {'__body__': u'helloworld'}>
    c                     t          |i || j        d<   | j                            dd           g | j        d<   | j        j        | j        d<   | j                            dd            d S )N_d__body__r   _partsrZ   )rU  rv  r  
setdefaultr  rZ   )r%   r  r<  s      r   r&   zTemplateResult.__init__  sk    "Annnd:s+++"$h"&+"4h:t,,,,,r   c                 4    | j                                         S r   )r  keysr$   s    r   r  zTemplateResult.keys  s    w||~~r   c                     | j         r]d                    | j                   }g | j         dd<   | j                            d          }|r||z   | j        d<   dS || j        d<   dS dS )z+Prepare value of __body__ by joining parts.r   Nr  )r  r^   r  r  )r%   rc   bodys      r   _prepare_bodyzTemplateResult._prepare_body  s{    ; 	,HHT[))EDKN7;;z**D ,&*Ul
###&+
###	, 	,r   c                 P    |dk    r|                                   | j        |         S Nr  r  r  r~  s     r   __getitem__zTemplateResult.__getitem__  s+    :   wt}r   c                 l    |dk    r|                                   | j                            ||          S r  )r  r  __setitem__rA  s      r   r  zTemplateResult.__setitem__  s7    :   w""4///r   c                 j    |dk    r|                                   | j                            |          S r  )r  r  __delitem__r~  s     r   r  zTemplateResult.__delitem__  s5    :   w""4(((r   c                 V    	 | |         S # t           $ r}t          |          d }~ww xY wr   KeyErrorr}  r%   keyks      r   r  zTemplateResult.__getattr__  s>    	$9 	$ 	$ 	$ ###	$s   
 
(#(c                     || |<   d S r   r   )r%   r  rc   s      r   __setattr__zTemplateResult.__setattr__  s    S			r   c                 P    	 | |= d S # t           $ r}t          |          d }~ww xY wr   r  r  s      r   __delattr__zTemplateResult.__delattr__  s?    	$S			 	$ 	$ 	$ ###	$s    
% %c                 :    |                                   | d         S r  r  r$   s    r   __unicode__zTemplateResult.__unicode__      Jr   c                 :    |                                   | d         S r  r  r$   s    r   __str__zTemplateResult.__str__  r  r   c                 >    |                                   d| j        z  S )Nz<TemplateResult: %s>r  r$   s    r   r   zTemplateResult.__repr__  s!    %//r   c                 4    | j                                         S r   )r  __len__r$   s    r   r  zTemplateResult.__len__  s    w   r   c              #   ~   K   | j                                         D ] }|dk    r|                                  |V  !d S r  )r  __iter__r  )r%   r   s     r   r  zTemplateResult.__iter__  sS      !!## 	 	AJ""$$$GGGG	 	r   N)r   r   r   r   r&   r  r  r  r  r  r  r  r  r  r  r   r  r  r   r   r   r  r    s         0- - -  	, 	, 	,  
0 0 0
) ) )
$ $ $  $ $ $          0 0 0! ! !    r   r  c                      dS )az  Doctest for testing template module.

    Define a utility function to run template test.

        >>> class TestResult:
        ...     def __init__(self, t): self.t = t
        ...     def __getattr__(self, name): return getattr(self.t, name)
        ...     def __repr__(self): return str(self.t)
        ...
        >>> def t(code, **keywords):
        ...     tmpl = Template(code, **keywords)
        ...     return lambda *a, **kw: TestResult(tmpl(*a, **kw))
        ...

    Simple tests.

        >>> t('1')()
        u'1\n'
        >>> t('$def with ()\n1')()
        u'1\n'
        >>> t('$def with (a)\n$a')(1)
        u'1\n'
        >>> t('$def with (a=0)\n$a')(1)
        u'1\n'
        >>> t('$def with (a=0)\n$a')(a=1)
        u'1\n'

    Test complicated expressions.

        >>> t('$def with (x)\n$x.upper()')('hello')
        u'HELLO\n'
        >>> t('$(2 * 3 + 4 * 5)')()
        u'26\n'
        >>> t('${2 * 3 + 4 * 5}')()
        u'26\n'
        >>> t('$def with (limit)\nkeep $(limit)ing.')('go')
        u'keep going.\n'
        >>> t('$def with (a)\n$a.b[0]')(storage(b=[1]))
        u'1\n'

    Test html escaping.

        >>> t('$def with (x)\n$x', filename='a.html')('<html>')
        u'&lt;html&gt;\n'
        >>> t('$def with (x)\n$x', filename='a.txt')('<html>')
        u'<html>\n'

    Test if, for and while.

        >>> t('$if 1: 1')()
        u'1\n'
        >>> t('$if 1:\n    1')()
        u'1\n'
        >>> t('$if 1:\n    1\\')()
        u'1'
        >>> t('$if 0: 0\n$elif 1: 1')()
        u'1\n'
        >>> t('$if 0: 0\n$elif None: 0\n$else: 1')()
        u'1\n'
        >>> t('$if 0 < 1 and 1 < 2: 1')()
        u'1\n'
        >>> t('$for x in [1, 2, 3]: $x')()
        u'1\n2\n3\n'
        >>> t('$def with (d)\n$for k, v in d.items(): $k')({1: 1})
        u'1\n'
        >>> t('$for x in [1, 2, 3]:\n\t$x')()
        u'    1\n    2\n    3\n'
        >>> t('$def with (a)\n$while a and a.pop():1')([1, 2, 3])
        u'1\n1\n1\n'

    The space after : must be ignored.

        >>> t('$if True: foo')()
        u'foo\n'

    Test loop.xxx.

        >>> t("$for i in range(5):$loop.index, $loop.parity")()
        u'1, odd\n2, even\n3, odd\n4, even\n5, odd\n'
        >>> t("$for i in range(2):\n    $for j in range(2):$loop.parent.parity $loop.parity")()
        u'odd odd\nodd even\neven odd\neven even\n'

    Test assignment.

        >>> t('$ a = 1\n$a')()
        u'1\n'
        >>> t('$ a = [1]\n$a[0]')()
        u'1\n'
        >>> t('$ a = {1: 1}\n$list(a.keys())[0]')()
        u'1\n'
        >>> t('$ a = []\n$if not a: 1')()
        u'1\n'
        >>> t('$ a = {}\n$if not a: 1')()
        u'1\n'
        >>> t('$ a = -1\n$a')()
        u'-1\n'
        >>> t('$ a = "1"\n$a')()
        u'1\n'

    Test comments.

        >>> t('$# 0')()
        u'\n'
        >>> t('hello$#comment1\nhello$#comment2')()
        u'hello\nhello\n'
        >>> t('$#comment0\nhello$#comment1\nhello$#comment2')()
        u'\nhello\nhello\n'

    Test unicode.

        >>> t('$def with (a)\n$a')(u'\u203d')
        u'\u203d\n'
        >>> t(u'$def with (a)\n$a $:a')(u'\u203d')
        u'\u203d \u203d\n'
        >>> t(u'$def with ()\nfoo')()
        u'foo\n'
        >>> def f(x): return x
        ...
        >>> t(u'$def with (f)\n$:f("x")')(f)
        u'x\n'
        >>> t('$def with (f)\n$:f("x")')(f)
        u'x\n'

    Test dollar escaping.

        >>> t("Stop, $$money isn't evaluated.")()
        u"Stop, $money isn't evaluated.\n"
        >>> t("Stop, \$money isn't evaluated.")()
        u"Stop, $money isn't evaluated.\n"

    Test space sensitivity.

        >>> t('$def with (x)\n$x')(1)
        u'1\n'
        >>> t('$def with(x ,y)\n$x')(1, 1)
        u'1\n'
        >>> t('$(1 + 2*3 + 4)')()
        u'11\n'

    Make sure globals are working.

        >>> t('$x')()
        Traceback (most recent call last):
            ...
        NameError: global name 'x' is not defined
        >>> t('$x', globals={'x': 1})()
        u'1\n'

    Can't change globals.

        >>> t('$ x = 2\n$x', globals={'x': 1})()
        u'2\n'
        >>> t('$ x = x + 1\n$x', globals={'x': 1})()
        Traceback (most recent call last):
            ...
        UnboundLocalError: local variable 'x' referenced before assignment

    Make sure builtins are customizable.

        >>> t('$min(1, 2)')()
        u'1\n'
        >>> t('$min(1, 2)', builtins={})()
        Traceback (most recent call last):
            ...
        NameError: global name 'min' is not defined

    Test vars.

        >>> x = t('$var x: 1')()
        >>> x.x
        u'1'
        >>> x = t('$var x = 1')()
        >>> x.x
        1
        >>> x = t('$var x:  \n    foo\n    bar')()
        >>> x.x
        u'foo\nbar\n'

    Test BOM chars.

        >>> t('\xef\xbb\xbf$def with(x)\n$x')('foo')
        u'foo\n'

    Test for with weird cases.

        >>> t('$for i in range(10)[1:5]:\n    $i')()
        u'1\n2\n3\n4\n'
        >>> t("$for k, v in sorted({'a': 1, 'b': 2}.items()):\n    $k $v", globals={'sorted':sorted})()
        u'a 1\nb 2\n'

    Test for syntax error.

        >>> try:
        ...     t("$for k, v in ({'a': 1, 'b': 2}.items():\n    $k $v")()
        ... except SyntaxError:
        ...     print("OK")
        ... else:
        ...     print("Expected SyntaxError")
        ...
        OK

    Test datetime.

        >>> import datetime
        >>> t("$def with (date)\n$date.strftime('%m %Y')")(datetime.datetime(2009, 1, 1))
        u'01 2009\n'

    Nr   r   r   r   r   r     s
    b 	Dr   __main__z	--compilerD   )Fr   r  r  r  sysr   ior   ru  netr   utilsr   r   r   r	   r  r
   __all__collections.abcr   r   r   r   r,   r]   r   r   rq   r   r  r  r   r|   r1  r5  r7  r9  r_   rj   r    r"   TEMPLATE_BUILTIN_NAMESrU  r  ry  r  r  r   r  r   r%  r   googler.  ImportErrorr   r<  	Exceptionr   r   r  NodeVisitorr  r  r   r   argvdoctesttestmodr   r   r   <module>r     s   < 


  				 



               < < < < < < < < < < < <         + * * * * *  $YF YF YF YF YF YF YF YFx1A 1A 1A 1A 1A 1A 1A 1Ah@ @ @ @ @ @ @ @0& & & & & & & &. . . . . . . .*4 4 4 4 4 4 4 4/ / / / / / / / 
G G G G G G G GP P P P Pi P P P. . . . . . . .. . . . . . . .	 	 	 	 	Y 	 	 		 	 	 	 	y 	 	 		 	 	 	 	y 	 	 	6 6 6 6 6i 6 6 6$	: 	: 	: 	: 	: 	: 	: 	:
# 
# 
# 
# 
# 
# 
# 
# 
  322$ $ $ L D *    "% "% "% "% "% "% "% "%JC C C C C C C C:) ) ) ) ) ) ) )Xw w w w w| w w wt	 	 	 	 	x 	 	 	\( \( \( \( \( \( \( \(~       > 
	        FVV 	 	 	D	T T T
- - -`	 	 	 	 	 	 	 		 	 	 	 	I 	 	 	W W W vR2 R2 R2 R2 R2#/ R2 R2 R2ja a a a a^ a a aHQ	 Q	 Q	h zch#(1+&&&&& s   2
F= =GG