o
    y?˜Yþ&  ã                   @   s\   d Z ddlZddlm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	dS )zÅA simple Python template renderer, for a nano-subset of Django syntax.

For a detailed discussion of this code, see this chapter from 500 Lines:
http://aosabook.org/en/500L/a-template-engine.html

é    N)Úenvc                   @   ó   e Zd ZdZdS )ÚTempliteSyntaxErrorz*Raised when a template has a syntax error.N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r
   r
   úC/var/www/html/env/lib/python3.10/site-packages/coverage/templite.pyr      ó    r   c                   @   r   )ÚTempliteValueErrorz7Raised when an expression won't evaluate in a template.Nr   r
   r
   r
   r   r      r   r   c                   @   sN   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdZdd„ Z	dd„ Z
dd„ ZdS )ÚCodeBuilderzBuild source code conveniently.r   c                 C   s   g | _ || _d S ©N)ÚcodeÚindent_level)ÚselfÚindentr
   r
   r   Ú__init__   s   
zCodeBuilder.__init__c                 C   s   d  dd„ | jD ƒ¡S )NÚ c                 s   ó   � | ]}t |ƒV  qd S r   )Ústr)Ú.0Úcr
   r
   r   Ú	<genexpr>$   ó   € z&CodeBuilder.__str__.<locals>.<genexpr>)Újoinr   ©r   r
   r
   r   Ú__str__#   s   zCodeBuilder.__str__c                 C   s   | j  d| j |dg¡ dS )zwAdd a line of source to the code.

        Indentation and newline will be added for you, don't provide them.

        ú Ú
N)r   Úextendr   )r   Úliner
   r
   r   Úadd_line&   s   zCodeBuilder.add_linec                 C   s   t | jƒ}| j |¡ |S )z!Add a section, a sub-CodeBuilder.)r   r   r   Úappend)r   Úsectionr
   r
   r   Úadd_section.   s   
zCodeBuilder.add_sectioné   c                 C   s   |  j | j7  _ dS )z0Increase the current indent for following lines.N©r   ÚINDENT_STEPr   r
   r
   r   r   6   ó   zCodeBuilder.indentc                 C   s   |  j | j8  _ dS )z0Decrease the current indent for following lines.Nr(   r   r
   r
   r   Údedent:   r*   zCodeBuilder.dedentc                 C   s(   | j dksJ ‚t| ƒ}i }t||ƒ |S )z:Execute the code, and return a dict of globals it defines.r   )r   r   Úexec)r   Úpython_sourceÚglobal_namespacer
   r
   r   Úget_globals>   s
   
zCodeBuilder.get_globalsN)r   )r   r   r   r	   r   r   r#   r&   r)   r   r+   r/   r
   r
   r
   r   r      s    
r   c                   @   sB   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zddd„Zdd„ Z	d
S )ÚTempliteaü  A simple template renderer, for a nano-subset of Django syntax.

    Supported constructs are extended variable access::

        {{var.modifier.modifier|filter|filter}}

    loops::

        {% for var in list %}...{% endfor %}

    and ifs::

        {% if var %}...{% endif %}

    Comments are within curly-hash markers::

        {# This will be ignored #}

    Any of these constructs can have a hypen at the end (`-}}`, `-%}`, `-#}`),
    which will collapse the whitespace following the tag.

    Construct a Templite with the template text, then use `render` against a
    dictionary context to create a finished string::

        templite = Templite('''
            <h1>Hello {{name|upper}}!</h1>
            {% for topic in topics %}
                <p>You are interested in {{topic}}.</p>
            {% endif %}
            ''',
            {'upper': str.upper},
        )
        text = templite.render({
            'name': "Ned",
            'topics': ['Python', 'Geometry', 'Juggling'],
        })

    c              	      s  i | _ |D ]}| j  |¡ qtƒ | _tƒ | _tƒ ‰ˆ d¡ ˆ ¡  ˆ ¡ }ˆ d¡ ˆ d¡ ˆ d¡ t	j
r>ˆ d¡ nˆ d¡ g ‰ ‡ ‡fdd„}g }t d	|¡}d
}|D ]ø}	|	 d¡�r?d\}
}|	d dk}|rnd}|	 d¡rtqX|	 d¡rŒ|  |	|
|…  ¡ ¡}ˆ  d| ¡ qX|ƒ  |	|
|…  ¡  ¡ }|d dkrÁt|ƒdkr«|  d|	¡ | d¡ ˆ d|  |d ¡ ¡ ˆ ¡  qX|d dkrüt|ƒdksÓ|d dkrÙ|  d|	¡ | d¡ |  |d | j¡ ˆ d|d |  |d ¡f ¡ ˆ ¡  qX|d  d¡�r6t|ƒdk�r|  d|	¡ |d dd … }|�s"|  d!|	¡ | ¡ }||k�r1|  d"|¡ ˆ ¡  qX|  d#|d ¡ qX|�rF|	 ¡ }	|	�rPˆ  t|	ƒ¡ qX|�r\|  d$|d% ¡ |ƒ  | j| j D ]}| d&||f ¡ �qeˆ d'¡ ˆ ¡  ˆ ¡ d( | _d S ))z¸Construct a Templite with the given `text`.

        `contexts` are dictionaries of values to use for future renderings.
        These are good for filters and global values.

        z&def render_function(context, do_dots):zresult = []zappend_result = result.appendzextend_result = result.extendzto_str = unicodezto_str = strc                      sN   t ˆ ƒdkrˆ dˆ d  ¡ nt ˆ ƒdkr ˆ dd ˆ ¡ ¡ ˆ dd…= dS )z%Force `buffered` to the code builder.é   zappend_result(%s)r   zextend_result([%s])ú, N)Úlenr#   r   r
   ©Úbufferedr   r
   r   Úflush_output�   s
   z'Templite.__init__.<locals>.flush_outputz(?s)({{.*?}}|{%.*?%}|{#.*?#})FÚ{)é   éþÿÿÿéýÿÿÿú-z{#z{{z
to_str(%s)r   Úifr8   zDon't understand ifzif %s:r1   Úforr'   ÚinzDon't understand forzfor c_%s in %s:é   ÚendzDon't understand endNzToo many endszMismatched end tagzDon't understand tagzUnmatched action tagéÿÿÿÿzc_%s = context[%r]zreturn "".join(result)Úrender_function)ÚcontextÚupdateÚsetÚall_varsÚ	loop_varsr   r#   r   r&   r   ÚPY2ÚreÚsplitÚ
startswithÚ
_expr_codeÚstripr$   r3   Ú_syntax_errorÚ	_variableÚpopr+   ÚlstripÚreprr/   Ú_render_function)r   ÚtextÚcontextsrC   Ú	vars_coder6   Ú	ops_stackÚtokensÚsquashÚtokenÚstartr@   ÚexprÚwordsÚend_whatÚ
start_whatÚvar_namer
   r4   r   r   q   s–   









þÿ


€
zTemplite.__init__c                 C   s¶   d|v r(|  d¡}|  |d ¡}|dd… D ]}|  || j¡ d||f }q|S d|v rN|  d¡}|  |d ¡}d dd	„ |dd… D ƒ¡}d
||f }|S |  || j¡ d| }|S )z(Generate a Python expression for `expr`.ú|r   r1   Nzc_%s(%s)Ú.r2   c                 s   r   r   )rR   )r   Údr
   r
   r   r   ò   r   z&Templite._expr_code.<locals>.<genexpr>zdo_dots(%s, %s)zc_%s)rJ   rL   rO   rF   r   )r   r\   Úpipesr   ÚfuncÚdotsÚargsr
   r
   r   rL   ç   s    
	ø
þzTemplite._expr_codec                 C   s   t d||f ƒ‚)z6Raise a syntax error using `msg`, and showing `thing`.z%s: %r)r   )r   ÚmsgÚthingr
   r
   r   rN   ù   s   zTemplite._syntax_errorc                 C   s&   t  d|¡s|  d|¡ | |¡ dS )z°Track that `name` is used as a variable.

        Adds the name to `vars_set`, a set of variable names.

        Raises an syntax error if `name` is not a valid name.

        z[_a-zA-Z][_a-zA-Z0-9]*$zNot a valid nameN)rI   ÚmatchrN   Úadd)r   ÚnameÚvars_setr
   r
   r   rO   ý   s   zTemplite._variableNc                 C   s&   t | jƒ}|r| |¡ |  || j¡S )z‚Render this template by applying it to `context`.

        `context` is a dictionary of values to use in this rendering.

        )ÚdictrC   rD   rS   Ú_do_dots)r   rC   Úrender_contextr
   r
   r   Úrender	  s   

zTemplite.renderc                 G   sn   |D ]2}zt ||ƒ}W n! ty,   z|| }W n ttfy)   td||f ƒ‚w Y nw t|ƒr4|ƒ }q|S )z(Evaluate dotted expressions at run-time.zCouldn't evaluate %r.%s)ÚgetattrÚAttributeErrorÚ	TypeErrorÚKeyErrorr   Úcallable)r   Úvaluerf   Údotr
   r
   r   ro     s"   
ÿÿÿþ€zTemplite._do_dotsr   )
r   r   r   r	   r   rL   rN   rO   rq   ro   r
   r
   r
   r   r0   J   s    &v
r0   )
r	   rI   Úcoverager   Ú
ValueErrorr   r   Úobjectr   r0   r
   r
   r
   r   Ú<module>   s   	.