
    /~h8*                        d Z ddlmZ ddlZddlmZmZmZmZ  G d de	      Z
 G d de	      Z G d	 d
      Z G d d      Zy)zA 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

    )annotationsN)AnyCallableNoReturncastc                      e Zd ZdZy)TempliteSyntaxErrorz*Raised when a template has a syntax error.N__name__
__module____qualname____doc__     Z/var/www/peopleoo.sandbox-dev.co.uk/venv/lib/python3.12/site-packages/coverage/templite.pyr	   r	      s    4r   r	   c                      e Zd ZdZy)TempliteValueErrorz7Raised when an expression won't evaluate in a template.Nr
   r   r   r   r   r      s    Ar   r   c                  N    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y
)CodeBuilderzBuild source code conveniently.c                     g | _         || _        y N)codeindent_level)selfindents     r   __init__zCodeBuilder.__init__#   s    -/	"r   c                F    dj                  d | j                  D              S )N c              3  2   K   | ]  }t        |        y wr   )str).0cs     r   	<genexpr>z&CodeBuilder.__str__.<locals>.<genexpr>(   s     1!s1v1   )joinr   r   s    r   __str__zCodeBuilder.__str__'   s    ww1tyy111r   c                Z    | j                   j                  d| j                  z  |dg       y)zwAdd a line of source to the code.

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

         
N)r   extendr   )r   lines     r   add_linezCodeBuilder.add_line*   s(     			# 1 114>?r   c                f    t        | j                        }| j                  j                  |       |S )z!Add a section, a sub-CodeBuilder.)r   r   r   append)r   sections     r   add_sectionzCodeBuilder.add_section2   s)    d//0		!r      c                B    | xj                   | j                  z  c_         y)z0Increase the current indent for following lines.Nr   INDENT_STEPr&   s    r   r   zCodeBuilder.indent:       T---r   c                B    | xj                   | j                  z  c_         y)z0Decrease the current indent for following lines.Nr4   r&   s    r   dedentzCodeBuilder.dedent>   r6   r   c                Z    | 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_namespaces      r   get_globalszCodeBuilder.get_globalsB   s8       A%%%D	+-],-r   N)r   )r   intreturnNone)r?   r    )r,   r    r?   r@   )r?   r   r?   r@   )r?   dict[str, Any])r   r   r   r   r   r'   r-   r1   r5   r   r8   r=   r   r   r   r   r       s0    )#2@ K..	 r   r   c                  B    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	y)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 #}

    Lines between `{% joined %}` and `{% endjoined %}` will have lines stripped
    and joined.  Be careful, this could join words together!

    Any of these constructs can have a hyphen at the end (`-}}`, `-%}`, `-#}`),
    which will collapse the white space 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           
     	   i | _         |D ]  }| j                   j                  |        t               | _        t               | _        t               j                  d       j                          j                         }j                  d       j                  d       j                  d       j                  d       g d0fd}g }t        j                  d|      }dx}}	|D ]  }
|
j                  d	      rid
\  }}|
d   dk(  }|rd}|
j                  d      r9|
j                  d      r7| j                  |
|| j                               }j                  d|z          |        |
|| j                         j                         }|d   dk(  rit        |      dk7  r| j!                  d|
       |j                  d       j                  d| j                  |d         z         j                          |d   dk(  rt        |      dk7  s|d   dk7  r| j!                  d|
       |j                  d       | j#                  |d   | j                         j                  d|d    d| j                  |d          d       j                          |d   dk(  r|j                  d       d}	|d   j                  d       r~t        |      dk7  r| j!                  d!|
       |d   dd" }|s| j!                  d#|
       |j%                         }||k7  r| j!                  d$|       |dk(  rd}	Vj'                          h| j!                  d%|d          |	r&t        j(                  d&d'|
j                               }
n|r|
j+                         }
|
sj                  t-        |
              |r| j!                  d(|d)           |        | j                  | j                  z
  D ]  }|j                  d*| d+|d,        j                  d-       j'                          t/        t0        t2        t4        t6        f   t0        d.t6        f   gt4        f   j9                         d/         | _        y")1zConstruct 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 = strc                     t               dk(  rj                  d d   z         n1t               dkD  r#j                  ddj                         z          dd= y)z%Force `buffered` to the code builder.   zappend_result(%s)r   zextend_result([%s]), N)lenr-   r%   )bufferedr   s   r   flush_outputz'Templite.__init__.<locals>.flush_output   sS    8}!1HQK?@X"3dii6IIJr   z(?s)({{.*?}}|{%.*?%}|{#.*?#})F{)   -z{#z{{z
to_str(%s)r   ifrM   zDon't understand ifzif %s:rG   forr2   inzDon't understand forzfor c_z in    :joinedTendzDon't understand endNzToo many endszMismatched end tagzDon't understand tagz\s*\n\s*r   zUnmatched action tagc_z = context[]zreturn ''.join(result).render_functionrA   )contextupdatesetall_vars	loop_varsr   r-   r   r1   resplit
startswith
_expr_codestripr/   rI   _syntax_error	_variablepopr8   sublstripreprr   r   dictr    r   r=   _render_function)r   textcontextsr\   	vars_coderK   	ops_stacktokenssquash	in_joinedtokenstartrW   exprwordsend_what
start_whatvar_namerJ   r   s                     @@r   r   zTemplite.__init__x   s&     	)GLL(	) #&%#&5 }>?$$&	m$5656n% 	 	 :DA"" ?	1E$"
s)s*C##D)%%d+??5s+;+A+A+CDDOOL4$78 !N!%,224::<EQx4'u:? ../DeL!((.hq1J&JKqU*u:?eAh$.> ../EuM!((/uQx@$U1XJd4??583L2MQO qX-!((2$(	q,,U3u:? ../EuM#(8AB<( ..F%.]]_
%1 ../CXN#x/(-I KKM**+A58L FF;EKKMBE!LLNEOODK0?	1B 5y}E6 	HHH:[AFG	H 	./ $c3h#s(!34 01!
r   c                   d|v rV|j                  d      }| j                  |d         }|dd D ]'  }| j                  || j                         d| d| d}) |S d|v rK|j                  d      }| j                  |d         }d	j	                  d
 |dd D              }d| d	| d}|S | j                  || j                         d|z  }|S )z(Generate a Python expression for `expr`.|r   rG   NrY   ().rH   c              3  2   K   | ]  }t        |        y wr   )rk   )r!   ds     r   r#   z&Templite._expr_code.<locals>.<genexpr>  s     7T!W7r$   zdo_dots(zc_%s)rb   rd   rg   r_   r%   )r   rw   pipesr   funcdotsargss          r   rd   zTemplite._expr_code   s    $;JJsOE??58,Dab	 +tT]]3D64&*+  D[::c?D??47+D997d12h77DdV2dV1-D  NN4/D=Dr   c                "    t        | d|      )z6Raise a syntax error using `msg`, and showing `thing`.z: )r	   )r   msgthings      r   rf   zTemplite._syntax_error  s    !SEE9"566r   c                v    t        j                  d|      s| j                  d|       |j                  |       y)zTrack 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)ra   matchrf   add)r   namevars_sets      r   rg   zTemplite._variable  s0     xx2D9148Tr   Nc                    t        | j                        }|r|j                  |       | j                  || j                        S )zRender this template by applying it to `context`.

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

        )rl   r\   r]   rm   _do_dots)r   r\   render_contexts      r   renderzTemplite.render  s:     dll+!!'*$$^T]]CCr   c           	         |D ]"  }	 t        ||      }t        |      s |       }$ |S # t        $ r3 	 ||   }n)# t        t        f$ r}t	        d|d|       |d}~ww xY wY Rw xY w)z(Evaluate dotted expressions at run-time.zCouldn't evaluate r   N)getattrAttributeError	TypeErrorKeyErrorr   callable)r   valuer   dotexcs        r   r   zTemplite._do_dots$  s     	 Cs+ 	   " !#JE!8, ,,UIQse< s/   *	A&:A&A 	AA  A&%A&)rn   r    ro   rB   r?   r@   )rw   r    r?   r    )r   r    r   r   r?   r   )r   r    r   zset[str]r?   r@   r   )r\   zdict[str, Any] | Noner?   r    )r   r   r   r    r?   r   )
r   r   r   r   r   rd   rf   rg   r   r   r   r   r   rD   rD   N   s)    (R|
|$7

Dr   rD   )r   
__future__r   ra   typingr   r   r   r   
ValueErrorr	   r   r   rD   r   r   r   <module>r      sK    # 	 
	* 	
	 	
+  + \d dr   