o
    b@                     @   s  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZ dd	lmZ dd
l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+m,Z, edZ-eZ.	 ee/e0e$e e"e#ee.df ee. ee.ddf e!ee. eee. e1e.f e+f Z2	 dee/e0f de/fddZ3dee/e0f de/fddZ4dee/ge1f dee/gdf fddZ5dee/e0f de/fddZ6dee/e0f de/fddZ7	d2de0deeee0e2f   d ee2 de2fd!d"Z8d#ee- dee- fd$d%Z9d&ee, d'e2dee/ge1f deeee0e2f   d(ee+ d)eee/e0f ge/f deeeee2 f ddf fd*d+Z:d&ee, d'e2dee/ge1f ddfd,d-Z;d&ee, d'e2dee/ge1f ded fd.d/Z<d&ee, d'e2dee/ fd0d1Z=dS )3zu
Context-free flattener/serializer for rendering Python objects, possibly
complex or arbitrarily nested, as strings.
    )iscoroutine)BytesIO)exc_info)
extract_tb)GeneratorType)AnyCallable	Coroutine	GeneratorListMappingOptionalSequenceTupleTypeVarUnioncast)DeferredensureDeferred)nativeString)Failure)CDATACharRefCommentTagslotvoidElements)FlattenerErrorUnfilledSlotUnsupportedType)IRenderableIRequestT.Ndatareturnc                 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.

    @param data: The string to escape.

    @return: The quoted form of C{data}.  If C{data} is L{str}, return a utf-8
        encoded string.
    utf-8   &s   &amp;   <s   &lt;   >   &gt;
isinstancestrencodereplacer#    r0   6/usr/lib/python3/dist-packages/twisted/web/_flatten.pyescapeForContentC   s   

r2   c                 C   s   t | tr
| dS | S )aG  
    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.

    @param data: The string to escape.

    @return: The string, unchanged, except for encoding.
    r%   )r+   r,   r-   r/   r0   r0   r1   attributeEscapingDoneOutsideV   s   

r3   writec                    s   dt ddf 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.
    r#   r$   Nc                    s    t | dd d S )N   "s   &quot;)r2   r.   r/   r4   r0   r1   _write   s   z*writeWithAttributeEscaping.<locals>._write)bytes)r4   r7   r0   r6   r1   writeWithAttributeEscapingi   s   )r9   c                 C   s    t | tr
| d} | ddS )z
    Escape CDATA for inclusion in a document.

    @param data: The string to escape.

    @return: The quoted form of C{data}. If C{data} is unicode, return a utf-8
        encoded string.
    r%      ]]>s   ]]]]><![CDATA[>r*   r/   r0   r0   r1   escapedCDATA   s   
	
r;   c                 C   sH   t | tr
| d} | dddd} | r"| dd dkr"| d	7 } | S )
z
    Escape a comment for inclusion in a document.

    @param data: The string to escape.

    @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/   r0   r0   r1   escapedComment   s   
	
r?   nameslotDatadefaultc                 C   sD   |ddd D ]}|dur| |v r||    S q|dur|S t | )zK
    Find the value of the named slot in the given stack of slot data.
    Nr<   )r   )r@   rA   rB   	slotFramer0   r0   r1   _getSlotValue   s   rD   dc                    sL   t  fdddtdtffdd}dtdtffdd	} || S )
z
    Create a new L{Deferred} based on C{d} that will fire and fail with C{d}'s
    result or error, but will not modify C{d}'s callback type.
    c                          S N)cancel_)rE   r0   r1   <lambda>       z_fork.<locals>.<lambda>resultr$   c                         |  | S rG   )callbackrM   d2r0   r1   rO         
z_fork.<locals>.callbackfailurec                    rN   rG   )errback)rT   rQ   r0   r1   rU      rS   z_fork.<locals>.errback)r   r"   r   addCallbacks)rE   rO   rU   r0   )rE   rR   r1   _fork   s
   rW   requestrootrenderFactorydataEscaperc                 #   sV   |||fdt dttttf gtf dtt dttgtf dtttt	t f ddf f
fdd d	t	t  dt	t  f fd
d}t
|ttfrP||| dS t
|trdt|j|j} |V  dS t
|trz|d |t|j |d dS t
|tr|d |t|j |d dS t
|tr@|j |j}|dur|du rtd| d|d}	d|	_||}
|
|	} |V    dS |js׈ |jV  dS |d t
|jtr|jd}n|j}|| |j  D ]%\}}t
|tr|d}|d| d   |t!t"|dV  |d q|js%t#|t$vr:|d  |jt%V  |d| d  dS |d dS t
|t&t't(frV|D ]} |V  qKdS t
|t)rkd|j*f }||d dS t
|t	rz|t+|V  dS t,|r|t	-t.t/t	t  tt f |V  dS t0|r|} ||dV  dS t1|)at  
    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 writes L{bytes} to C{write}.
        It can 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 be another generator, in which
        case it is iterated.  See L{_flattenTree} for the trampoline that
        consumes said values.
    newRootr[   rZ   r4   r$   Nc                    s   t  | |||S rG   )_flattenElement)r\   r[   rZ   r4   )rX   rA   r0   r1   	keepGoing
  s   z"_flattenElement.<locals>.keepGoingrM   c                    s
   |   S rG   )addCallbackrP   )r^   r0   r1   keepGoingAsync  s   
z'_flattenElement.<locals>.keepGoingAsyncs	   <![CDATA[r:   s   <!--s   -->z$Tag wants to be rendered by method "z)" but is not contained in any IRenderableFr'   asciir>   s   ="r6   r5   r(   s   </s    />z&#%d;)rZ   )2Flattenabler   r   r8   r,   r   r    objectr
   r   r+   r   rD   r@   rB   r   r;   r#   r   r?   r   appendrA   render
ValueErrorclonelookupRenderMethodpoptagNamechildrenr-   
attributesitemsr3   r9   r   r   r2   tuplelistr   r   ordinalrW   r   fromCoroutiner   r	   
providedByr   )rX   rY   r4   rA   rZ   r[   r`   	slotValuerendererName	rootClonerenderMethodrM   rj   kvelementescapedr0   )r^   rX   rA   r1   r]      s   1














r]   c           	   
      s   t | ||g dtg}|rmz|d j}t|d }t|tr#|I dH }W n? ty1   |  Y n8 tyc } z'|  g }|D ]}|	|jj
d  q@|	|j
d  t||tt d d}~ww |	| |sdS 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: A C{Deferred}-returning coroutine that resolves to C{None}.
    Nr<   rY      )r]   r2   gi_framenextr+   r   StopIterationri   	Exceptionrd   f_localsr   r   r   )	rX   rY   r4   stackframery   eroots	generatorr0   r0   r1   _flattenTreel  s.   



r   c                 C   s   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{str},
        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 with C{None} when C{root}
        has been completely flattened into C{write} or which will be errbacked
        if an unexpected exception occurs.
    )r   r   )rX   rY   r4   r0   r0   r1   flatten  s   r   c                    s4   t   t| | j}| fdd ttt |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 UTF-8 encoded
        string as its result when C{root} has been completely flattened or which
        will be errbacked if an unexpected exception occurs.
    c                    rF   rG   )getvaluerI   ior0   r1   rK     rL   zflattenString.<locals>.<lambda>)r   r   r4   r_   r   r   r8   )rX   rY   rE   r0   r   r1   flattenString  s   r   rG   )>__doc__inspectr   r   r   sysr   	tracebackr   typesr   typingr   r   r	   r
   r   r   r   r   r   r   r   r   twisted.internet.deferr   r   twisted.python.compatr   twisted.python.failurer   twisted.web._stanr   r   r   r   r   r   twisted.web.errorr   r   r   twisted.web.iwebr    r!   r"   FlattenableRecursiver8   r,   rc   rb   r2   r3   r9   r;   r?   rD   rW   r]   r   r   r   r0   r0   r0   r1   <module>   s   8 

/


 
*
"