U
    ¹êW[(>  ã                   @   s4  d Z ddlmZmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ zddlmZ W n ek
rp   dd	„ ZY nX dd
lmZmZmZ ddlmZmZ ddlmZmZmZmZmZmZ ddlmZmZm Z  ddl!m"Z" dd„ Z#dd„ Z$dd„ Z%dd„ Z&dd„ Z'd&dd„Z(dd„ Z)dd„ Z*d d!„ Z+d"d#„ Z,d$d%„ Z-dS )'zu
Context-free flattener/serializer for rendering Python objects, possibly
complex or arbitrarily nested, as strings.
é    )ÚdivisionÚabsolute_import)ÚBytesIO)Úexc_info)ÚGeneratorType)Ú
extract_tb)Úiscoroutinec                  O   s   dS )NF© )ÚargsÚkwargsr	   r	   ú6/usr/lib/python3/dist-packages/twisted/web/_flatten.pyr      s    r   )ÚunicodeÚnativeStringÚ	iteritems)ÚDeferredÚensureDeferred)ÚTagÚslotÚvoidElementsÚCommentÚCDATAÚCharRef)ÚUnfilledSlotÚUnsupportedTypeÚFlattenerError)ÚIRenderablec                 C   s4   t | tƒr|  d¡} |  dd¡ dd¡ dd¡} | S )aØ  
    Escape some character or UTF-8 byte data for inclusion in an HTML or XML
    document, by replacing metacharacters (C{&<>}) with their entity
    equivalents (C{&amp;&lt;&gt;}).

    This is used as an input to L{_flattenElement}'s C{dataEscaper} parameter.

    @type data: C{bytes} or C{unicode}
    @param data: The string to escape.

    @rtype: C{bytes}
    @return: The quoted form of C{data}.  If C{data} is unicode, return a utf-8
        encoded string.
    úutf-8ó   &s   &amp;ó   <s   &lt;ó   >ó   &gt;©Ú
isinstancer   ÚencodeÚreplace©Údatar	   r	   r   ÚescapeForContent    s    

 ÿ þr'   c                 C   s   t | tƒr|  d¡S | S )aƒ  
    Escape some character or UTF-8 byte data for inclusion in the top level of
    an attribute.  L{attributeEscapingDoneOutside} actually passes the data
    through unchanged, because L{writeWithAttributeEscaping} handles the
    quoting of the text within attributes outside the generator returned by
    L{_flattenElement}; this is used as the C{dataEscaper} argument to that
    L{_flattenElement} call so that that generator does not redundantly escape
    its text output.

    @type data: C{bytes} or C{unicode}
    @param data: The string to escape.

    @return: The string, unchanged, except for encoding.
    @rtype: C{bytes}
    r   )r"   r   r#   r%   r	   r	   r   ÚattributeEscapingDoneOutside8   s    

r(   c                    s   ‡ fdd„}|S )aU  
    Decorate a C{write} callable so that all output written is properly quoted
    for inclusion within an XML attribute value.

    If a L{Tag <twisted.web.template.Tag>} C{x} is flattened within the context
    of the contents of another L{Tag <twisted.web.template.Tag>} C{y}, the
    metacharacters (C{<>&"}) delimiting C{x} should be passed through
    unchanged, but the textual content of C{x} should still be quoted, as
    usual.  For example: C{<y><x>&amp;</x></y>}.  That is the default behavior
    of L{_flattenElement} when L{escapeForContent} is passed as the
    C{dataEscaper}.

    However, when a L{Tag <twisted.web.template.Tag>} C{x} is flattened within
    the context of an I{attribute} of another L{Tag <twisted.web.template.Tag>}
    C{y}, then the metacharacters delimiting C{x} should be quoted so that it
    can be parsed from the attribute's value.  In the DOM itself, this is not a
    valid thing to do, but given that renderers and slots may be freely moved
    around in a L{twisted.web.template} template, it is a condition which may
    arise in a document and must be handled in a way which produces valid
    output.  So, for example, you should be able to get C{<y attr="&lt;x /&gt;"
    />}.  This should also be true for other XML/HTML meta-constructs such as
    comments and CDATA, so if you were to serialize a L{comment
    <twisted.web.template.Comment>} in an attribute you should get C{<y
    attr="&lt;-- comment --&gt;" />}.  Therefore in order to capture these
    meta-characters, flattening is done with C{write} callable that is wrapped
    with L{writeWithAttributeEscaping}.

    The final case, and hopefully the much more common one as compared to
    serializing L{Tag <twisted.web.template.Tag>} and arbitrary L{IRenderable}
    objects within an attribute, is to serialize a simple string, and those
    should be passed through for L{writeWithAttributeEscaping} to quote
    without applying a second, redundant level of quoting.

    @param write: A callable which will be invoked with the escaped L{bytes}.

    @return: A callable that writes data with escaping.
    c                    s   ˆ t | ƒ dd¡ƒ d S )Nó   "s   &quot;)r'   r$   r%   ©Úwriter	   r   Ú_writet   s    z*writeWithAttributeEscaping.<locals>._writer	   )r+   r,   r	   r*   r   ÚwriteWithAttributeEscapingN   s    &r-   c                 C   s    t | tƒr|  d¡} |  dd¡S )zû
    Escape CDATA for inclusion in a document.

    @type data: L{str} or L{unicode}
    @param data: The string to escape.

    @rtype: L{str}
    @return: The quoted form of C{data}. If C{data} is unicode, return a utf-8
        encoded string.
    r   ó   ]]>s   ]]]]><![CDATA[>r!   r%   r	   r	   r   ÚescapedCDATAz   s    

r/   c                 C   sH   t | tƒr|  d¡} |  dd¡ dd¡} | rD| dd… dkrD| d	7 } | S )
zÿ
    Escape a comment for inclusion in a document.

    @type data: L{str} or L{unicode}
    @param data: The string to escape.

    @rtype: C{str}
    @return: The quoted form of C{data}. If C{data} is unicode, return a utf-8
        encoded string.
    r   s   --s   - - r   r    éÿÿÿÿNó   -ó    r!   r%   r	   r	   r   ÚescapedComment‹   s    

r3   Nc                 C   sH   |ddd… D ] }|dk	r| |kr||    S q|dk	r<|S t | ƒ‚dS )zK
    Find the value of the named slot in the given stack of slot data.
    Nr0   )r   )ÚnameÚslotDataÚdefaultZ	slotFramer	   r	   r   Ú_getSlotValueŸ   s    r7   c                 #   sÐ  |||f‡‡fdd„	‰ t |ttfƒr4|||ƒƒ n˜t |tƒr\t|jˆ|jƒ}ˆ |ƒV  npt |tƒrˆ|dƒ |t|j	ƒƒ |dƒ nDt |t
ƒr´|dƒ |t|j	ƒƒ |dƒ nt |tƒrˆ |j¡ |jdk	r|j}| d¡}d|_| |¡}	|	ˆ|ƒ}
ˆ |
ƒV  ˆ ¡  dS |js0ˆ |jƒV  dS |d	ƒ t |jtƒrT|j d
¡}n|j}||ƒ t|jƒD ]L\}}t |tƒrŠ| d
¡}|d| d ƒ ˆ |tt|ƒdV  |dƒ ql|jsÐt|ƒtkrø|dƒ ˆ |jtƒV  |d| d ƒ n|dƒ nÊt |tttfƒr,|D ]}ˆ |ƒV  qn t |t ƒrTd|j!f }|| d
¡ƒ nxt |t"ƒrv| #‡ fdd„¡V  nVt$|ƒržt%|ƒ}| #‡ fdd„¡V  n.t& '|¡rÄ| ˆ¡}
ˆ |
|dV  nt(|ƒ‚dS )a<  
    Make C{root} slightly more flat by yielding all its immediate contents as
    strings, deferreds or generators that are recursive calls to itself.

    @param request: A request object which will be passed to
        L{IRenderable.render}.

    @param root: An object to be made flatter.  This may be of type C{unicode},
        L{str}, L{slot}, L{Tag <twisted.web.template.Tag>}, L{tuple}, L{list},
        L{types.GeneratorType}, L{Deferred}, or an object that implements
        L{IRenderable}.

    @param write: A callable which will be invoked with each L{bytes} produced
        by flattening C{root}.

    @param slotData: A L{list} of L{dict} mapping L{str} slot names to data
        with which those slots will be replaced.

    @param renderFactory: If not L{None}, an object that provides
        L{IRenderable}.

    @param dataEscaper: A 1-argument callable which takes L{bytes} or
        L{unicode} and returns L{bytes}, quoted as appropriate for the
        rendering context.  This is really only one of two values:
        L{attributeEscapingDoneOutside} or L{escapeForContent}, depending on
        whether the rendering context is within an attribute or not.  See the
        explanation in L{writeWithAttributeEscaping}.

    @return: An iterator that eventually yields L{bytes} that should be written
        to the output.  However it may also yield other iterators or
        L{Deferred}s; if it yields another iterator, the caller will iterate
        it; if it yields a L{Deferred}, the result of that L{Deferred} will
        either be L{bytes}, in which case it's written, or another generator,
        in which case it is iterated.  See L{_flattenTree} for the trampoline
        that consumes said values.
    @rtype: An iterator which yields L{bytes}, L{Deferred}, and more iterators
        of the same type.
    c                    s   t ˆ | |ˆ||ƒS ©N)Ú_flattenElement)ZnewRootÚdataEscaperÚrenderFactoryr+   )Úrequestr5   r	   r   Ú	keepGoingÕ   s    
 ÿz"_flattenElement.<locals>.keepGoings	   <![CDATA[r.   s   <!--s   -->NFr   Úasciir2   s   ="r*   r)   r   s   </s    />z&#%d;c                    s   | ˆ | ƒfS r8   r	   ©Úresult©r=   r	   r   Ú<lambda>  ó    z!_flattenElement.<locals>.<lambda>c                    s   | ˆ | ƒfS r8   r	   r?   rA   r	   r   rB     rC   )r;   ))r"   Úbytesr   r   r7   r4   r6   r   r/   r&   r   r3   r   Úappendr5   ZrenderZcloneZlookupRenderMethodÚpopÚtagNameZchildrenr#   r   Z
attributesr(   r-   r   r   r'   ÚtupleÚlistr   r   Zordinalr   ÚaddCallbackr   r   r   Z
providedByr   )r<   Úrootr+   r5   r;   r:   Z	slotValueZrendererNameZ	rootCloneZrenderMethodr@   rG   ÚkÚvÚelementZescapedÚdr	   )r=   r<   r5   r   r9   ­   s„    ( ÿ







ý


r9   c           	   
   #   sò   t | ||g dtƒg‰ ˆ rîzˆ d j}tˆ d ƒ}W nŠ tk
rN   ˆ  ¡  Y q tk
r¼ } zRˆ  ¡  g }ˆ D ]}| |jjd ¡ qn| |jd ¡ t	||t
tƒ d ƒƒ‚W 5 d}~X Y qX t|tƒrâ‡ fdd„}| |¡V  qˆ  |¡ qdS )a\  
    Make C{root} into an iterable of L{bytes} and L{Deferred} by doing a depth
    first traversal of the tree.

    @param request: A request object which will be passed to
        L{IRenderable.render}.

    @param root: An object to be made flatter.  This may be of type C{unicode},
        L{bytes}, L{slot}, L{Tag <twisted.web.template.Tag>}, L{tuple},
        L{list}, L{types.GeneratorType}, L{Deferred}, or something providing
        L{IRenderable}.

    @param write: A callable which will be invoked with each L{bytes} produced
        by flattening C{root}.

    @return: An iterator which yields objects of type L{bytes} and L{Deferred}.
        A L{Deferred} is only yielded when one is encountered in the process of
        flattening C{root}.  The returned iterator must not be iterated again
        until the L{Deferred} is called back.
    Nr0   rK   é   c                    s   | \}}ˆ   |¡ |S r8   )rE   )ZoriginalAndToFlattenÚoriginalZ	toFlatten©Ústackr	   r   ÚcbxM  s    
z_flattenTree.<locals>.cbx)r9   r'   Úgi_frameÚnextÚStopIterationrF   Ú	ExceptionrE   Úf_localsr   r   r   r"   r   rJ   )	r<   rK   r+   ÚframerN   ÚeÚrootsÚ	generatorrT   r	   rR   r   Ú_flattenTree(  s$    
(
r^   c                    sd   zt ˆƒ}W n0 tk
r*   ˆ  d¡ Y q`   ˆ  ¡  Y q`X ‡ ‡‡fdd„}| |ˆ j¡ q`q dS )a¥  
    Take strings from an iterator and pass them to a writer function.

    @param state: An iterator of L{str} and L{Deferred}.  L{str} instances will
        be passed to C{write}.  L{Deferred} instances will be waited on before
        resuming iteration of C{state}.

    @param write: A callable which will be invoked with each L{str}
        produced by iterating C{state}.

    @param result: A L{Deferred} which will be called back when C{state} has
        been completely flattened into C{write} or which will be errbacked if
        an exception in a generator passed to C{state} or an errback from a
        L{Deferred} from state occurs.

    @return: L{None}
    Nc                    s   t ˆˆˆ ƒ | S r8   )Ú_writeFlattenedData)rQ   ©r@   Ústater+   r	   r   Úcbyp  s    z _writeFlattenedData.<locals>.cby)rV   rW   ÚcallbackZerrbackZaddCallbacks)ra   r+   r@   rN   rb   r	   r`   r   r_   V  s    r_   c                 C   s"   t ƒ }t| ||ƒ}t|||ƒ |S )aü  
    Incrementally write out a string representation of C{root} using C{write}.

    In order to create a string representation, C{root} will be decomposed into
    simpler objects which will themselves be decomposed and so on until strings
    or objects which can easily be converted to strings are encountered.

    @param request: A request object which will be passed to the C{render}
        method of any L{IRenderable} provider which is encountered.

    @param root: An object to be made flatter.  This may be of type L{unicode},
        L{bytes}, L{slot}, L{Tag <twisted.web.template.Tag>}, L{tuple},
        L{list}, L{types.GeneratorType}, L{Deferred}, or something that provides
        L{IRenderable}.

    @param write: A callable which will be invoked with each L{bytes} produced
        by flattening C{root}.

    @return: A L{Deferred} which will be called back when C{root} has been
        completely flattened into C{write} or which will be errbacked if an
        unexpected exception occurs.
    )r   r^   r_   )r<   rK   r+   r@   ra   r	   r	   r   Úflattenx  s    rd   c                    s*   t ƒ ‰ t| |ˆ jƒ}| ‡ fdd„¡ |S )aË  
    Collate a string representation of C{root} into a single string.

    This is basically gluing L{flatten} to an L{io.BytesIO} and returning
    the results. See L{flatten} for the exact meanings of C{request} and
    C{root}.

    @return: A L{Deferred} which will be called back with a single string as
        its result when C{root} has been completely flattened into C{write} or
        which will be errbacked if an unexpected exception occurs.
    c                    s   ˆ   ¡ S r8   )Úgetvalue)Ú_©Úior	   r   rB   ¤  rC   zflattenString.<locals>.<lambda>)r   rd   r+   rJ   )r<   rK   rO   r	   rg   r   ÚflattenString–  s    ri   )N).Ú__doc__Z
__future__r   r   rh   r   Úsysr   Útypesr   Ú	tracebackr   Úinspectr   ÚImportErrorZtwisted.python.compatr   r   r   Ztwisted.internet.deferr   r   Ztwisted.web._stanr   r   r   r   r   r   Ztwisted.web.errorr   r   r   Ztwisted.web.iwebr   r'   r(   r-   r/   r3   r7   r9   r^   r_   rd   ri   r	   r	   r	   r   Ú<module>   s2    ,
{."