U
    ª€ljÁF  ã                   @  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 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Z0ee1e2e&e"e$e%ee0df ee0 ee0ddf e#ee0 eee0 e3e0f e-f Z4dZ5dddœdd„Z6dddœdd„Z7dddœdd„Z8dddœdd „Z9dddœd!d"„Z:dAd#d$d%d&d'œd(d)„Z;d*d*d+œd,d-„Z<d.d&dd/d0d1d2d3œd4d5„Z=d.d&dd6d7œd8d9„Z>d.d&dd:d7œd;d<„Z?d.d&d=d>œd?d@„Z@dS )Bzu
Context-free flattener/serializer for rendering Python objects, possibly
complex or arbitrarily nested, as strings.
é    )Úannotations)Ú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.Ni   zUnion[bytes, str]Úbytes©Ú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;ó   >s   &gt;©Ú
isinstanceÚstrÚencodeÚreplace©r&   © r2   ú8/tmp/pip-unpacked-wheel-aghyhbke/twisted/web/_flatten.pyÚescapeForContentG   s    

r4   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/   r1   r2   r2   r3   ÚattributeEscapingDoneOutsideZ   s    

r5   úCallable[[bytes], object]zCallable[[bytes], None])Úwriter'   c                   s   dddœ‡ 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$   ÚNoner%   c                   s   ˆ t | ƒ dd¡ƒ d S )Nó   "s   &quot;)r4   r0   r1   ©r7   r2   r3   Ú_write–   s    z*writeWithAttributeEscaping.<locals>._writer2   )r7   r;   r2   r:   r3   ÚwriteWithAttributeEscapingm   s    )r<   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,   r1   r2   r2   r3   ÚescapedCDATAœ   s    	

r>   c                 C  s@   t | tƒr|  d¡} |  dd¡} | r<| dd… dkr<| d7 } | S )aÜ  
    Within comments the sequence C{-->} can be mistaken as the end of the comment.
    To ensure consistent parsing and valid output the sequence is replaced with C{--&gt;}.
    Furthermore, whitespace is added when a comment ends in a dash. This is done to break
    the connection of the ending C{-} with the closing C{-->}.

    @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   --&gt;éÿÿÿÿNó   -ó    r,   r1   r2   r2   r3   ÚescapedCommentª   s    

rC   r.   z-Sequence[Optional[Mapping[str, Flattenable]]]zOptional[Flattenable]ÚFlattenable)ÚnameÚslotDataÚdefaultr'   c                 C  sB   t |ƒD ] }|dk	r| |kr||    S q|dk	r6|S t| ƒ‚dS )zK
    Find the value of the named slot in the given stack of slot data.
    N)Úreversedr   )rE   rF   rG   Z	slotFramer2   r2   r3   Ú_getSlotValue¾   s    rI   zDeferred[T])Údr'   c                   sH   t ‡ fdd„ƒ‰dddœ‡fdd„}dddœ‡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   ˆ   ¡ S ©N)Úcancel©Ú_)rJ   r2   r3   Ú<lambda>Ô   ó    z_fork.<locals>.<lambda>r#   ©Úresultr'   c                   s   ˆ   | ¡ | S rK   )Úcallback©rR   ©Úd2r2   r3   rS   Ö   s    
z_fork.<locals>.callbackr   )Úfailurer'   c                   s   ˆ   | ¡ | S rK   )Úerrback)rW   rU   r2   r3   rX   Ú   s    
z_fork.<locals>.errback)r   ZaddCallbacks)rJ   rS   rX   r2   )rJ   rV   r3   Ú_forkÏ   s
    rY   zOptional[IRequest]z)List[Optional[Mapping[str, Flattenable]]]úOptional[IRenderable]ú$Callable[[Union[bytes, str]], bytes]zMGenerator[Union[Generator[Any, Any, Any], Deferred[Flattenable]], None, None])ÚrequestÚrootr7   rF   ÚrenderFactoryÚdataEscaperr'   c                 #  s  |||fddddddœ‡‡fdd„‰ d	d	d
œ‡ fdd„}t |ttfƒrV|||ƒƒ �n²t |tƒr~t|jˆ|jƒ}ˆ |ƒV  �nŠt |tƒrª|dƒ |t|j	ƒƒ |dƒ �n^t |t
ƒrÖ|dƒ |t|j	ƒƒ |dƒ �n2t |tƒ�r<ˆ |j¡ |j}|dk	�rR|dk�rtd|› d�ƒ‚| d¡}	d|	_| |¡}
|
ˆ|	ƒ}ˆ |ƒV  ˆ ¡  dS |j�sjˆ |jƒV  dS |dƒ t |jtƒ�rŽ|j d¡}n|j}||ƒ |j ¡ D ]L\}}t |tƒ�rÄ| d¡}|d| d ƒ ˆ |tt|ƒd�V  |dƒ �q¦|j�s
t|ƒtk�r2|dƒ ˆ |jtƒV  |d| d ƒ n|dƒ nÌt |ttt fƒ�rf|D ]}ˆ |ƒV  �qRn¢t |t!ƒ�rŽd|j"f }|| d¡ƒ nzt |t#ƒ�rª|t$|ƒƒV  n^t%|ƒ�rÚ|t# &t't(t#t) t*t)f |ƒ¡ƒV  n.t+ ,|¡�r | ˆ¡}ˆ ||d�V  nt-|ƒ‚dS ) 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.
    rD   r[   rZ   r6   z@Generator[Union[Flattenable, Deferred[Flattenable]], None, None])ÚnewRootr_   r^   r7   r'   c                   s   t ˆ | |ˆ||ƒS rK   )Ú_flattenElement)r`   r_   r^   r7   )r\   rF   r2   r3   Ú	keepGoing  s         ÿz"_flattenElement.<locals>.keepGoingzDeferred[Flattenable]rQ   c                   s
   |   ˆ ¡S rK   )ÚaddCallbackrT   )rb   r2   r3   ÚkeepGoingAsync  s    z'_flattenElement.<locals>.keepGoingAsyncs	   <![CDATA[r=   s   <!--r?   Nz$Tag wants to be rendered by method "z)" but is not contained in any IRenderableFr*   ÚasciirB   s   ="r:   r9   r+   s   </s    />z&#%d;)r^   ).r-   r$   r.   r   rI   rE   rG   r   r>   r&   r   rC   r   ÚappendrF   ÚrenderÚ
ValueErrorÚcloneZlookupRenderMethodÚpopÚtagNameÚchildrenr/   Ú
attributesÚitemsr5   r<   r   r   r4   ÚtupleÚlistr   r   Zordinalr   rY   r   ZfromCoroutiner   r
   rD   Úobjectr!   Z
providedByr    )r\   r]   r7   rF   r^   r_   rd   Z	slotValueZrendererNameZ	rootCloneZrenderMethodrR   rk   ÚkÚvÚelementÚescapedr2   )rb   r\   rF   r3   ra   â   s”    1ü






ÿ




  ÿ

ÿÿ
ra   r8   )r\   r]   r7   r'   c           	   
   ƒ  s  g ‰ d‰dddœ‡ ‡‡fdd„}ddœ‡ ‡‡fdd	„‰t | ||g d
tƒg}|�rz*t|d ƒ}t|tƒrxˆƒ  |I d
H }W n„ tk
r–   | ¡  Y qJ tk
rþ } zLg }|D ] }|jd
k	r®| 	|jj
d ¡ q®| ¡  t||ttƒ d ƒƒ‚W 5 d
}~X Y qJX | 	|¡ qJˆƒ  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}.
    r   r$   r8   )Úbsr'   c                   s(   ˆ   | ¡ ˆt| ƒ7 ‰ˆtkr$ˆƒ  d S rK   )rf   ÚlenÚBUFFER_SIZE)rv   )ÚbufÚbufSizeÚflushBufferr2   r3   ÚbufferedWriteŒ  s    
z#_flattenTree.<locals>.bufferedWrite)r'   c                     s(   ˆdkr$ˆd  ˆ ¡ƒ ˆ d d …= d‰d S )Nr   rP   )Újoinr2   )ry   rz   r7   r2   r3   r{   ˜  s    
z!_flattenTree.<locals>.flushBufferNr@   r]   é   )ra   r4   Únextr-   r   ÚStopIterationrj   Ú	ExceptionÚgi_framerf   Úf_localsr   r   r   )	r\   r]   r7   r|   Ústackrt   ÚeÚrootsÚ	generatorr2   )ry   rz   r{   r7   r3   Ú_flattenTrees  s.    ÿ

(rˆ   zDeferred[None]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ˆ   )r\   r]   r7   r2   r2   r3   Úflatten»  s    r‰   zDeferred[bytes])r\   r]   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                   s   ˆ   ¡ S rK   )ÚgetvaluerM   ©Úior2   r3   rO   å  rP   zflattenString.<locals>.<lambda>)r   r‰   r7   rc   r   r   r$   )r\   r]   rJ   r2   r‹   r3   ÚflattenString×  s    r�   )N)AÚ__doc__Ú
__future__r   Úinspectr   rŒ   r   Úsysr   Ú	tracebackr   Útypesr   Útypingr   r	   r
   r   r   r   r   r   r   r   r   r   Ztwisted.internet.deferr   r   Ztwisted.python.compatr   Ztwisted.python.failurer   Ztwisted.web._stanr   r   r   r   r   r   Ztwisted.web.errorr   r   r    Ztwisted.web.iwebr!   r"   r#   ZFlattenableRecursiver$   r.   rq   rD   rx   r4   r5   r<   r>   rC   rI   rY   ra   rˆ   r‰   r�   r2   r2   r2   r3   Ú<module>   sZ   8 
ôÿ/ ý H