B
    \'                 @   sH  d Z ddlZddlm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mZ ddlmZmZmZ ddlmZmZmZmZmZmZmZmZ ddlZejrddlmZmZ d	ZG d
d dZe Z e!e!e!dddZ"G dd de#Z$G dd de#Z%G dd de%Z&G dd de%Z'G dd de#Z(G dd de(Z)G dd de(Z*G dd de(Z+G dd  d e(Z,G d!d" d"e(Z-G d#d$ d$e(Z.G d%d& d&e(Z/G d'd( d(e(Z0G d)d* d*e(Z1G d+d, d,e(Z2G d-d. d.e2Z3G d/d0 d0e(Z4G d1d2 d2e5Z6G d3d4 d4e#Z7G d5d6 d6e#Z8e!e!d7d8d9Z9d=e8e$e!e!e*d:d;d<Z:dS )>a  A simple template system that compiles templates to Python code.

Basic usage looks like::

    t = template.Template("<html>{{ myvalue }}</html>")
    print(t.generate(myvalue="XXX"))

`Loader` is a class that loads templates from a root directory and caches
the compiled templates::

    loader = template.Loader("/home/btaylor")
    print(loader.load("test.html").generate(myvalue="XXX"))

We compile all templates to raw Python. Error-reporting is currently... uh,
interesting. Syntax for the templates::

    ### base.html
    <html>
      <head>
        <title>{% block title %}Default title{% end %}</title>
      </head>
      <body>
        <ul>
          {% for student in students %}
            {% block student %}
              <li>{{ escape(student.name) }}</li>
            {% end %}
          {% end %}
        </ul>
      </body>
    </html>

    ### bold.html
    {% extends "base.html" %}

    {% block title %}A bolder title{% end %}

    {% block student %}
      <li><span style="bold">{{ escape(student.name) }}</span></li>
    {% end %}

Unlike most other template systems, we do not put any restrictions on the
expressions you can include in your statements. ``if`` and ``for`` blocks get
translated exactly into Python, so you can do complex expressions like::

   {% for student in [p for p in people if p.student and p.age > 23] %}
     <li>{{ escape(student.name) }}</li>
   {% end %}

Translating directly to Python means you can apply functions to expressions
easily, like the ``escape()`` function in the examples above. You can pass
functions in to your template just like any other variable
(In a `.RequestHandler`, override `.RequestHandler.get_template_namespace`)::

   ### Python code
   def add(x, y):
      return x + y
   template.execute(add=add)

   ### The template
   {{ add(1, 2) }}

We provide the functions `escape() <.xhtml_escape>`, `.url_escape()`,
`.json_encode()`, and `.squeeze()` to all templates by default.

Typical applications do not create `Template` or `Loader` instances by
hand, but instead use the `~.RequestHandler.render` and
`~.RequestHandler.render_string` methods of
`tornado.web.RequestHandler`, which load templates automatically based
on the ``template_path`` `.Application` setting.

Variable names beginning with ``_tt_`` are reserved by the template
system and should not be used by application code.

Syntax Reference
----------------

Template expressions are surrounded by double curly braces: ``{{ ... }}``.
The contents may be any python expression, which will be escaped according
to the current autoescape setting and inserted into the output.  Other
template directives use ``{% %}``.

To comment out a section so that it is omitted from the output, surround it
with ``{# ... #}``.

These tags may be escaped as ``{{!``, ``{%!``, and ``{#!``
if you need to include a literal ``{{``, ``{%``, or ``{#`` in the output.


``{% apply *function* %}...{% end %}``
    Applies a function to the output of all template code between ``apply``
    and ``end``::

        {% apply linkify %}{{name}} said: {{message}}{% end %}

    Note that as an implementation detail apply blocks are implemented
    as nested functions and thus may interact strangely with variables
    set via ``{% set %}``, or the use of ``{% break %}`` or ``{% continue %}``
    within loops.

``{% autoescape *function* %}``
    Sets the autoescape mode for the current file.  This does not affect
    other files, even those referenced by ``{% include %}``.  Note that
    autoescaping can also be configured globally, at the `.Application`
    or `Loader`.::

        {% autoescape xhtml_escape %}
        {% autoescape None %}

``{% block *name* %}...{% end %}``
    Indicates a named, replaceable block for use with ``{% extends %}``.
    Blocks in the parent template will be replaced with the contents of
    the same-named block in a child template.::

        <!-- base.html -->
        <title>{% block title %}Default title{% end %}</title>

        <!-- mypage.html -->
        {% extends "base.html" %}
        {% block title %}My page title{% end %}

``{% comment ... %}``
    A comment which will be removed from the template output.  Note that
    there is no ``{% end %}`` tag; the comment goes from the word ``comment``
    to the closing ``%}`` tag.

``{% extends *filename* %}``
    Inherit from another template.  Templates that use ``extends`` should
    contain one or more ``block`` tags to replace content from the parent
    template.  Anything in the child template not contained in a ``block``
    tag will be ignored.  For an example, see the ``{% block %}`` tag.

``{% for *var* in *expr* %}...{% end %}``
    Same as the python ``for`` statement.  ``{% break %}`` and
    ``{% continue %}`` may be used inside the loop.

``{% from *x* import *y* %}``
    Same as the python ``import`` statement.

``{% if *condition* %}...{% elif *condition* %}...{% else %}...{% end %}``
    Conditional statement - outputs the first section whose condition is
    true.  (The ``elif`` and ``else`` sections are optional)

``{% import *module* %}``
    Same as the python ``import`` statement.

``{% include *filename* %}``
    Includes another template file.  The included file can see all the local
    variables as if it were copied directly to the point of the ``include``
    directive (the ``{% autoescape %}`` directive is an exception).
    Alternately, ``{% module Template(filename, **kwargs) %}`` may be used
    to include another template with an isolated namespace.

``{% module *expr* %}``
    Renders a `~tornado.web.UIModule`.  The output of the ``UIModule`` is
    not escaped::

        {% module Template("foo.html", arg=42) %}

    ``UIModules`` are a feature of the `tornado.web.RequestHandler`
    class (and specifically its ``render`` method) and will not work
    when the template system is used on its own in other contexts.

``{% raw *expr* %}``
    Outputs the result of the given expression without autoescaping.

``{% set *x* = *y* %}``
    Sets a local variable.

``{% try %}...{% except %}...{% else %}...{% finally %}...{% end %}``
    Same as the python ``try`` statement.

``{% while *condition* %}... {% end %}``
    Same as the python ``while`` statement.  ``{% break %}`` and
    ``{% continue %}`` may be used inside the loop.

``{% whitespace *mode* %}``
    Sets the whitespace mode for the remainder of the current file
    (or until the next ``{% whitespace %}`` directive). See
    `filter_whitespace` for available options. New in Tornado 4.3.
    N)StringIO)escape)app_log)
ObjectDictexec_inunicode_type)AnyUnionCallableListDictIterableOptionalTextIO)TupleContextManagerxhtml_escapec               @   s   e Zd ZdS )_UnsetMarkerN)__name__
__module____qualname__ r   r   /lib/python3.7/site-packages/tornado/template.pyr      s   r   )modetextreturnc             C   sZ   | dkr|S | dkr4t dd|}t dd|}|S | dkrJt dd|S td	|  d
S )a  Transform whitespace in ``text`` according to ``mode``.

    Available modes are:

    * ``all``: Return all whitespace unmodified.
    * ``single``: Collapse consecutive whitespace with a single whitespace
      character, preserving newlines.
    * ``oneline``: Collapse all runs of whitespace into a single space
      character, removing all newlines in the process.

    .. versionadded:: 4.3
    allsinglez([\t ]+) z
(\s*\n\s*)
Zonelinez(\s+)zinvalid whitespace mode %sN)resub	Exception)r   r   r   r   r   filter_whitespace   s    r#   c            	   @   s   e Zd ZdZddeedfeeef edeee	f eee	f eddddZ
eedd	d
Zed edddZed ed dddZdS )TemplatezA compiled template.

    We compile into Python from the given template_string. You can generate
    the template from variables with generate().
    z<string>N
BaseLoader)template_stringnameloadercompress_whitespace
autoescape
whitespacer   c       	      C   sR  t || _|tk	r0|dk	r$td|r,dnd}|dkrh|rJ|jrJ|j}n|ds^|drdd}nd}|dk	sttt|d t	|t
s|| _n|r|j| _nt| _|r|jni | _t|t ||}t| t|| | _| || _|| _y,tt | jd| jd	d
 ddd| _W n6 tk
rL   t| j }td| j|  Y nX dS )a  Construct a Template.

        :arg str template_string: the contents of the template file.
        :arg str name: the filename from which the template was loaded
            (used for error message).
        :arg tornado.template.BaseLoader loader: the `~tornado.template.BaseLoader` responsible
            for this template, used to resolve ``{% include %}`` and ``{% extend %}`` directives.
        :arg bool compress_whitespace: Deprecated since Tornado 4.3.
            Equivalent to ``whitespace="single"`` if true and
            ``whitespace="all"`` if false.
        :arg str autoescape: The name of a function in the template
            namespace, or ``None`` to disable escaping by default.
        :arg str whitespace: A string specifying treatment of whitespace;
            see `filter_whitespace` for options.

        .. versionchanged:: 4.3
           Added ``whitespace`` parameter; deprecated ``compress_whitespace``.
        Nz2cannot set both whitespace and compress_whitespacer   r   z.htmlz.js z%s.generated.py._execT)dont_inheritz%s code:
%s)r   Z
native_strr'   _UNSETr"   r+   endswithAssertionErrorr#   
isinstancer   r*   _DEFAULT_AUTOESCAPE	namespace_TemplateReader_File_parsefile_generate_pythoncoder(   compileZ
to_unicodereplacecompiled_format_coderstripr   error)	selfr&   r'   r(   r)   r*   r+   readerZformatted_coder   r   r   __init__  sB    




zTemplate.__init__)kwargsr   c                s   t jt jt jt jt jt jtt jtt	f j
ddt fdddd}| j || t j| ttg t	f |d }t  | S )z0Generate this template with the given arguments.r-   r.   c                s    j S )N)r<   )r'   )rC   r   r   <lambda>_  s    z#Template.generate.<locals>.<lambda>)
get_source)r   r   
url_escapejson_encodesqueezelinkifydatetimeZ_tt_utf8Z_tt_string_typesr   
__loader__Z_tt_execute)r   r   rI   rJ   rK   rL   rM   utf8r   bytesr'   r>   r   updater6   r   r?   typingcastr
   	linecache
clearcache)rC   rF   r6   Zexecuter   )rC   r   generateP  s"    
zTemplate.generate)r(   r   c             C   sp   t  }zZi }| |}|  x|D ]}||| q$W t||||d j}|d | | S |  X d S )Nr   )	r   _get_ancestorsreversefind_named_blocks_CodeWritertemplaterV   getvalueclose)rC   r(   buffernamed_blocks	ancestorsZancestorwriterr   r   r   r;   k  s    

zTemplate._generate_pythonr8   c             C   sV   | j g}xH| j jjD ]:}t|tr|s.td||j| j}||	| qW |S )Nz1{% extends %} block found, but no template loader)
r:   bodychunksr4   _ExtendsBlock
ParseErrorloadr'   extendrW   )rC   r(   r`   chunkr[   r   r   r   rW   z  s    
zTemplate._get_ancestors)r   r   r   __doc__r1   r	   strrP   boolr   rE   r   rV   r   r;   r   rW   r   r   r   r   r$      s   (Cr$   c               @   sz   e Zd ZdZeddfeeeef eddddZddddZ	deeed	d
dZ
deeed	ddZeedddZdS )r%   zBase class for template loaders.

    You must use a template loader to use template constructs like
    ``{% extends %}`` and ``{% include %}``. The loader caches all
    templates after they are loaded the first time.
    N)r*   r6   r+   r   c             C   s*   || _ |pi | _|| _i | _t | _dS )a  Construct a template loader.

        :arg str autoescape: The name of a function in the template
            namespace, such as "xhtml_escape", or ``None`` to disable
            autoescaping by default.
        :arg dict namespace: A dictionary to be added to the default template
            namespace, or ``None``.
        :arg str whitespace: A string specifying default behavior for
            whitespace in templates; see `filter_whitespace` for options.
            Default is "single" for files ending in ".html" and ".js" and
            "all" for other files.

        .. versionchanged:: 4.3
           Added ``whitespace`` parameter.
        N)r*   r6   r+   	templates	threadingRLocklock)rC   r*   r6   r+   r   r   r   rE     s
    
zBaseLoader.__init__)r   c          	   C   s   | j  i | _W dQ R X dS )z'Resets the cache of compiled templates.N)ro   rl   )rC   r   r   r   reset  s    zBaseLoader.reset)r'   parent_pathr   c             C   s
   t  dS )z@Converts a possibly-relative path to absolute (used internally).N)NotImplementedError)rC   r'   rq   r   r   r   resolve_path  s    zBaseLoader.resolve_pathc          	   C   sD   | j ||d}| j& || jkr0| || j|< | j| S Q R X dS )zLoads a template.)rq   N)rs   ro   rl   _create_template)rC   r'   rq   r   r   r   rf     s
    
zBaseLoader.load)r'   r   c             C   s
   t  d S )N)rr   )rC   r'   r   r   r   rt     s    zBaseLoader._create_template)N)N)r   r   r   ri   r5   rj   r   r   rE   rp   rs   r$   rf   rt   r   r   r   r   r%     s   r%   c                   sN   e Zd ZdZeedd fddZdeeedddZeed	d
dZ	  Z
S )Loaderz?A template loader that loads from a single root directory.
    N)root_directoryrF   r   c                s$   t t| jf | tj|| _d S )N)superru   rE   ospathabspathroot)rC   rv   rF   )	__class__r   r   rE     s    zLoader.__init__)r'   rq   r   c             C   s   |r~| ds~| ds~| ds~tj| j|}tjtj|}tjtj||}| | jr~|t| jd d  }|S )N</   )
startswithrx   ry   joinr{   dirnamerz   len)rC   r'   rq   Zcurrent_pathfile_dirZrelative_pathr   r   r   rs     s    


zLoader.resolve_path)r'   r   c          	   C   s<   t j| j|}t|d}t| || d}|S Q R X d S )Nrb)r'   r(   )rx   ry   r   r{   openr$   read)rC   r'   ry   fr[   r   r   r   rt     s    zLoader._create_template)N)r   r   r   ri   rj   r   rE   rs   r$   rt   __classcell__r   r   )r|   r   ru     s   ru   c                   sV   e Zd ZdZeeef edd fddZdeeedddZee	d	d
dZ
  ZS )
DictLoaderz/A template loader that loads from a dictionary.N)dictrF   r   c                s   t t| jf | || _d S )N)rw   r   rE   r   )rC   r   rF   )r|   r   r   rE     s    zDictLoader.__init__)r'   rq   r   c             C   sB   |r>| ds>| ds>| ds>t|}tt||}|S )Nr}   r~   )r   	posixpathr   normpathr   )rC   r'   rq   r   r   r   r   rs     s    



zDictLoader.resolve_path)r'   r   c             C   s   t | j| || dS )N)r'   r(   )r$   r   )rC   r'   r   r   r   rt     s    zDictLoader._create_template)N)r   r   r   ri   r   rj   r   rE   rs   r$   rt   r   r   r   )r|   r   r     s   r   c               @   sL   e Zd Zed  dddZdddddZee ee	d	f dd
ddZ
dS )_Node)r   c             C   s   dS )Nr   r   )rC   r   r   r   
each_child  s    z_Node.each_childrZ   N)ra   r   c             C   s
   t  d S )N)rr   )rC   ra   r   r   r   rV     s    z_Node.generate_NamedBlock)r(   r_   r   c             C   s"   x|   D ]}||| q
W d S )N)r   rY   )rC   r(   r_   Zchildr   r   r   rY     s    z_Node.find_named_blocks)r   r   r   r   r   rV   r   r%   r   rj   rY   r   r   r   r   r     s   r   c               @   s@   e Zd ZedddddZddddd	Zed
 dddZdS )r8   
_ChunkListN)r[   rb   r   c             C   s   || _ || _d| _d S )Nr   )r[   rb   line)rC   r[   rb   r   r   r   rE     s    z_File.__init__rZ   )ra   r   c          	   C   s\   | d| j | < | d| j | d| j | j| | d| j W d Q R X d S )Nzdef _tt_execute():z_tt_buffer = []z_tt_append = _tt_buffer.appendz$return _tt_utf8('').join(_tt_buffer))
write_liner   indentrb   rV   )rC   ra   r   r   r   rV     s    
z_File.generater   )r   c             C   s   | j fS )N)rb   )rC   r   r   r   r     s    z_File.each_child)r   r   r   r$   rE   rV   r   r   r   r   r   r   r8     s   r8   c               @   sB   e Zd Zee ddddZdddddZed	 d
ddZdS )r   N)rc   r   c             C   s
   || _ d S )N)rc   )rC   rc   r   r   r   rE     s    z_ChunkList.__init__rZ   )ra   r   c             C   s   x| j D ]}|| qW d S )N)rc   rV   )rC   ra   rh   r   r   r   rV     s    z_ChunkList.generater   )r   c             C   s   | j S )N)rc   )rC   r   r   r   r     s    z_ChunkList.each_child)	r   r   r   r   r   rE   rV   r   r   r   r   r   r   r     s   r   c               @   sb   e Zd ZeeeeddddZed dddZ	d	dd
ddZ
ee eed f ddddZdS )r   N)r'   rb   r[   r   r   c             C   s   || _ || _|| _|| _d S )N)r'   rb   r[   r   )rC   r'   rb   r[   r   r   r   r   rE   $  s    z_NamedBlock.__init__r   )r   c             C   s   | j fS )N)rb   )rC   r   r   r   r   *  s    z_NamedBlock.each_childrZ   )ra   r   c          	   C   s8   |j | j }||j| j |j| W d Q R X d S )N)r_   r'   includer[   r   rb   rV   )rC   ra   blockr   r   r   rV   -  s    z_NamedBlock.generate)r(   r_   r   c             C   s   | || j < t| || d S )N)r'   r   rY   )rC   r(   r_   r   r   r   rY   2  s    
z_NamedBlock.find_named_blocks)r   r   r   rj   r   r$   intrE   r   r   rV   r   r%   r   rY   r   r   r   r   r   #  s
   r   c               @   s   e Zd ZeddddZdS )rd   N)r'   r   c             C   s
   || _ d S )N)r'   )rC   r'   r   r   r   rE   :  s    z_ExtendsBlock.__init__)r   r   r   rj   rE   r   r   r   r   rd   9  s   rd   c               @   sN   e Zd ZededdddZee eee	f ddddZ
d	dd
ddZdS )_IncludeBlockr7   N)r'   rD   r   r   c             C   s   || _ |j | _|| _d S )N)r'   template_namer   )rC   r'   rD   r   r   r   r   rE   ?  s    z_IncludeBlock.__init__)r(   r_   r   c             C   s.   |d k	st || j| j}|j|| d S )N)r3   rf   r'   r   r:   rY   )rC   r(   r_   includedr   r   r   rY   D  s    z_IncludeBlock.find_named_blocksrZ   )ra   r   c          	   C   sL   |j d k	st|j | j| j}||| j |jj	| W d Q R X d S )N)
r(   r3   rf   r'   r   r   r   r:   rb   rV   )rC   ra   r   r   r   r   rV   K  s    z_IncludeBlock.generate)r   r   r   rj   r   rE   r   r%   r   r   rY   rV   r   r   r   r   r   >  s   r   c               @   sB   e Zd ZeeeddddZed dddZd	dd
ddZ	dS )_ApplyBlockN)methodr   rb   r   c             C   s   || _ || _|| _d S )N)r   r   rb   )rC   r   r   rb   r   r   r   rE   S  s    z_ApplyBlock.__init__r   )r   c             C   s   | j fS )N)rb   )rC   r   r   r   r   X  s    z_ApplyBlock.each_childrZ   )ra   r   c          	   C   s   d|j  }| j d7  _ |d| | j | < |d| j |d| j | j| |d| j W d Q R X |d| j|f | j d S )Nz_tt_apply%dr   z	def %s():z_tt_buffer = []z_tt_append = _tt_buffer.appendz$return _tt_utf8('').join(_tt_buffer)z_tt_append(_tt_utf8(%s(%s()))))apply_counterr   r   r   rb   rV   r   )rC   ra   Zmethod_namer   r   r   rV   [  s    

z_ApplyBlock.generate)
r   r   r   rj   r   r   rE   r   r   rV   r   r   r   r   r   R  s   r   c               @   sB   e Zd ZeeeddddZee dddZddd	d
dZ	dS )_ControlBlockN)	statementr   rb   r   c             C   s   || _ || _|| _d S )N)r   r   rb   )rC   r   r   rb   r   r   r   rE   j  s    z_ControlBlock.__init__)r   c             C   s   | j fS )N)rb   )rC   r   r   r   r   o  s    z_ControlBlock.each_childrZ   )ra   r   c          	   C   sF   | d| j | j |   | j| | d| j W d Q R X d S )Nz%s:pass)r   r   r   r   rb   rV   )rC   ra   r   r   r   rV   r  s    
z_ControlBlock.generate)
r   r   r   rj   r   r   rE   r   r   rV   r   r   r   r   r   i  s   r   c               @   s.   e Zd ZeeddddZdddddZdS )	_IntermediateControlBlockN)r   r   r   c             C   s   || _ || _d S )N)r   r   )rC   r   r   r   r   r   rE   {  s    z"_IntermediateControlBlock.__init__rZ   )ra   r   c             C   s0   | d| j | d| j | j| d  d S )Nr   z%s:r   )r   r   r   indent_size)rC   ra   r   r   r   rV     s    z"_IntermediateControlBlock.generate)r   r   r   rj   r   rE   rV   r   r   r   r   r   z  s   r   c               @   s.   e Zd ZeeddddZdddddZdS )	
_StatementN)r   r   r   c             C   s   || _ || _d S )N)r   r   )rC   r   r   r   r   r   rE     s    z_Statement.__init__rZ   )ra   r   c             C   s   | | j| j d S )N)r   r   r   )rC   ra   r   r   r   rV     s    z_Statement.generate)r   r   r   rj   r   rE   rV   r   r   r   r   r     s   r   c               @   s2   e Zd Zd
eeeddddZddddd	ZdS )_ExpressionFN)
expressionr   rawr   c             C   s   || _ || _|| _d S )N)r   r   r   )rC   r   r   r   r   r   r   rE     s    z_Expression.__init__rZ   )ra   r   c             C   sj   | d| j | j | d| j | d| j | jsX|jjd k	rX| d|jj | j | d| j d S )Nz_tt_tmp = %szEif isinstance(_tt_tmp, _tt_string_types): _tt_tmp = _tt_utf8(_tt_tmp)z&else: _tt_tmp = _tt_utf8(str(_tt_tmp))z_tt_tmp = _tt_utf8(%s(_tt_tmp))z_tt_append(_tt_tmp))r   r   r   r   current_templater*   )rC   ra   r   r   r   rV     s    
z_Expression.generate)F)r   r   r   rj   r   rk   rE   rV   r   r   r   r   r     s   r   c                   s&   e Zd Zeedd fddZ  ZS )_ModuleN)r   r   r   c                s   t t| jd| |dd d S )Nz_tt_modules.T)r   )rw   r   rE   )rC   r   r   )r|   r   r   rE     s    z_Module.__init__)r   r   r   rj   r   rE   r   r   r   )r|   r   r     s   r   c               @   s0   e Zd ZeeeddddZdddddZdS )	_TextN)valuer   r+   r   c             C   s   || _ || _|| _d S )N)r   r   r+   )rC   r   r   r+   r   r   r   rE     s    z_Text.__init__rZ   )ra   r   c             C   s:   | j }d|krt| j|}|r6|dt| | j d S )Nz<pre>z_tt_append(%r))r   r#   r+   r   r   rO   r   )rC   ra   r   r   r   r   rV     s
    z_Text.generate)r   r   r   rj   r   rE   rV   r   r   r   r   r     s   r   c               @   s4   e Zd ZdZd
eeeddddZeddd	ZdS )re   zRaised for template syntax errors.

    ``ParseError`` instances have ``filename`` and ``lineno`` attributes
    indicating the position of the error.

    .. versionchanged:: 4.3
       Added ``filename`` and ``lineno`` attributes.
    Nr   )messagefilenamelinenor   c             C   s   || _ || _|| _d S )N)r   r   r   )rC   r   r   r   r   r   r   rE     s    zParseError.__init__)r   c             C   s   d| j | j| jf S )Nz%s at %s:%d)r   r   r   )rC   r   r   r   __str__  s    zParseError.__str__)Nr   )r   r   r   ri   rj   r   rE   r   r   r   r   r   re     s   re   c               @   sr   e Zd Zeeeef ee e	ddddZ
edddZddd	d
Ze	eddddZdeeeddddZdS )rZ   N)r:   r_   r(   r   r   c             C   s.   || _ || _|| _|| _d| _g | _d| _d S )Nr   )r:   r_   r(   r   r   include_stack_indent)rC   r:   r_   r(   r   r   r   r   rE     s    z_CodeWriter.__init__)r   c             C   s   | j S )N)r   )rC   r   r   r   r     s    z_CodeWriter.indent_sizer   c                s   G  fdddt }| S )Nc                   s2   e Zd Zdd fddZedd fddZdS )	z$_CodeWriter.indent.<locals>.IndenterrZ   )r   c                s     j d7  _  S )Nr   )r   )r.   )rC   r   r   	__enter__  s    z._CodeWriter.indent.<locals>.Indenter.__enter__N)argsr   c                s     j dkst  j d8  _ d S )Nr   r   )r   r3   )r.   r   )rC   r   r   __exit__  s    z-_CodeWriter.indent.<locals>.Indenter.__exit__)r   r   r   r   r   r   r   )rC   r   r   Indenter  s   r   )object)rC   r   r   )rC   r   r     s    	z_CodeWriter.indent)r[   r   r   c                s2    j  j|f | _G  fdddt}| S )Nc                   s2   e Zd Zdd fddZedd fddZdS )	z,_CodeWriter.include.<locals>.IncludeTemplaterZ   )r   c                s    S )Nr   )r.   )rC   r   r   r     s    z6_CodeWriter.include.<locals>.IncludeTemplate.__enter__N)r   r   c                s    j  d  _d S )Nr   )r   popr   )r.   r   )rC   r   r   r     s    z5_CodeWriter.include.<locals>.IncludeTemplate.__exit__)r   r   r   r   r   r   r   )rC   r   r   IncludeTemplate  s   r   )r   appendr   r   )rC   r[   r   r   r   )rC   r   r     s    z_CodeWriter.include)r   line_numberr   r   c             C   sh   |d kr| j }d| jj|f }| jrJdd | jD }|ddt| 7 }td| | | | jd d S )Nz	  # %s:%dc             S   s   g | ]\}}d |j |f qS )z%s:%d)r'   ).0Ztmplr   r   r   r   
<listcomp>  s    z*_CodeWriter.write_line.<locals>.<listcomp>z	 (via %s)z, z    )r:   )r   r   r'   r   r   reversedprintr:   )rC   r   r   r   Zline_commentr`   r   r   r   r     s    z_CodeWriter.write_line)N)r   r   r   r   r   rj   r   r   r%   r$   rE   r   r   r   r   r   r   r   r   r   rZ     s   
	rZ   c               @   s   e Zd ZeeeddddZdeeeedddZdeed	d
dZedddZedddZ	e
eef edddZedddZeddddZdS )r7   N)r'   r   r+   r   c             C   s"   || _ || _|| _d| _d| _d S )Nr   r   )r'   r   r+   r   pos)rC   r'   r   r+   r   r   r   rE   
  s
    z_TemplateReader.__init__r   )needlestartendr   c             C   sn   |dkst || j}||7 }|d kr6| j||}n$||7 }||ksJt | j|||}|dkrj||8 }|S )Nr   )r3   r   r   find)rC   r   r   r   r   indexr   r   r   r     s    z_TemplateReader.find)countr   c             C   sX   |d krt | j| j }| j| }|  j| jd| j|7  _| j| j| }|| _|S )Nr   )r   r   r   r   r   )rC   r   Znewpossr   r   r   consume  s    
z_TemplateReader.consume)r   c             C   s   t | j| j S )N)r   r   r   )rC   r   r   r   	remaining(  s    z_TemplateReader.remainingc             C   s   |   S )N)r   )rC   r   r   r   __len__+  s    z_TemplateReader.__len__)keyr   c             C   s   t |tr`t| }||\}}}|d kr2| j}n
|| j7 }|d k	rN|| j7 }| jt||| S |dk rr| j| S | j| j|  S d S )Nr   )r4   slicer   indicesr   r   )rC   r   sizer   stopstepr   r   r   __getitem__.  s    



z_TemplateReader.__getitem__c             C   s   | j | jd  S )N)r   r   )rC   r   r   r   r   >  s    z_TemplateReader.__str__)msgr   c             C   s   t || j| jd S )N)re   r'   r   )rC   r   r   r   r   raise_parse_errorA  s    z!_TemplateReader.raise_parse_error)r   N)N)r   r   r   rj   rE   r   r   r   r   r   r	   r   r   r   r   r   r   r   r   r7   	  s   	r7   )r<   r   c                s<   |   }dttt|d   d fddt|D S )Nz%%%dd  %%s
r   r,   c                s    g | ]\}} |d  |f qS )r   r   )r   ir   )formatr   r   r   H  s    z _format_code.<locals>.<listcomp>)
splitlinesr   reprr   	enumerate)r<   linesr   )r   r   r@   E  s    r@   )rD   r[   in_blockin_loopr   c             C   sb  t g }xRd}x| d|}|dks6|d |  krh|rH| d|  |jt|  | j| j	 |S | |d  dkr|d7 }q|d |  k r| |d  dkr| |d  dkr|d7 }qP qW |dkr| |}|jt|| j| j	 | d}| j}|  r6| d dkr6| d |jt||| j	 q|d	krx| d
}	|	dkr^| d | |	
 }
| d q|dkr| d}	|	dkr| d | |	
 }
| d |
s| d |jt|
| q|dkst|| d}	|	dkr| d | |	
 }
| d |
s4| d |
d\}}}|
 }tddddgtdgtdgtdgd}||}|d k	r|s| d||f  ||kr| d||f  |jt|
| qq|dkr|s| d |S |dkrR|dkr
q|d kr@|
d!
d"}|s4| d# t|}n|d$krf|sZ| d% t|
|}n|d&kr|
d!
d"}|s| d' t|| |}n|d(kr|s| d) t||}n~|d*kr|
 }|d+krd }||_qnT|d,kr|
 }t|d- || _	qn.|d.kr.t||d/d0}n|d1krBt||}|j| qq|d2kr|d3krvt| |||}n(|d4krt| ||d }nt| |||}|d4kr|s| d5 t|||}n6|d6kr|s| d7 t||||}nt|
||}|j| qq|d8krL|s6| d|tddgf  |jt|
| qq| d9|  qW d S ):Nr   {r   r   z Missing {%% end %%} block for %s)r   %#   !z{#z#}zMissing end comment #}z{{z}}zMissing end expression }}zEmpty expressionz{%z%}zMissing end block %}zEmpty block tag ({% %})r   ifforwhiletry)elseelifexceptfinallyz%s outside %s blockz'%s block cannot be attached to %s blockr   zExtra {% end %} block)
extendsr   setimportfromcommentr*   r+   r   moduler   r   "'zextends missing file path)r   r   zimport missing statementr   zinclude missing file pathr   zset missing statementr*   Noner+   r,   r   T)r   r   )applyr   r   r   r   r   )r   r   r   zapply missing method namer   zblock missing name)breakcontinuezunknown operator: %r)r   r   r   r   rc   r   r   r   r   r+   stripr   r3   	partitionr   getr   rd   r   r   r*   r#   r   r9   r   r   r   )rD   r[   r   r   rb   ZcurlyZconsZstart_bracer   r   contentsoperatorZspacesuffixZintermediate_blocksZallowed_parentsr   fnr   Z
block_bodyr   r   r   r9   K  s   
















































r9   )NN);ri   rM   ior   rT   os.pathrx   r   r    rm   Ztornador   Ztornado.logr   Ztornado.utilr   r   r   rR   r   r	   r
   r   r   r   r   r   ZTYPE_CHECKINGr   r   r5   r   r1   rj   r#   r   r$   r%   ru   r   r   r8   r   r   rd   r   r   r   r   r   r   r   r   r"   re   rZ   r7   r@   r9   r   r   r   r   <module>   sV   ( =	8<	 
