o
    brV                     @   sR  d Z ddlZddlZddl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 ddlmZ ddlmZ dd	lmZmZmZmZ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$ ddl%m&Z&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6 G dd de6eZ7dd j8j9Z:G dd de Z;dS )zf
Tests for the flattening portion of L{twisted.web.template}, implemented in
L{twisted.web._flatten}.
    N)OrderedDictdedent)FunctionType)CallableDictListNoReturnOptionalcast)XML)implementer)CancelledErrorDeferredgatherResultspassthrusucceed)Failure)XMLAssertionMixin)SynchronousTestCase)FlattenerErrorUnfilledSlotUnsupportedType)IRenderableIRequestITemplateLoader)CDATACharRefCommentElementFlattenableTag	TagLoaderflattenStringrendererslottags)FlattenTestCasec                   @   sz  e Zd ZdZdBddZdBddZdBdd	ZdBd
dZdBddZde	e
gef de	egef ddfddZdBddZdBddZdBddZdBddZdBddZdBddZde	egef ddfddZdBd d!ZdBd"d#ZdBd$d%ZdBd&d'Zdeee  fd(d)ZdBd*d+ZdBd,d-ZdBd.d/ZdBd0d1Z dBd2d3Z!dBd4d5Z"dBd6d7Z#dBd8d9Z$dBd:d;Z%dBd<d=Z&dBd>d?Z'dBd@dAZ(dS )CSerializationTestsz.
    Tests for flattening various things.
    returnNc                 C   s    |  tjtdddd dS )z:
        Test that nested tags flatten correctly.
        42there)his'   <html hi="there"><body>42</body></html>N)assertFlattensImmediatelyr&   htmlbodyself r2   ?/usr/lib/python3/dist-packages/twisted/web/test/test_flatten.pytest_nestedTags5   s   z"SerializationTests.test_nestedTagsc                 C   s    |  ddf |  ddf dS )zL
        Test that strings will be flattened and escaped correctly.
        ones   onez
<abc&&>123s   &lt;abc&amp;&amp;&gt;123N)r-   r0   r2   r2   r3   test_serializeString>   s   z'SerializationTests.test_serializeStringc                 C   s   |  t d dS )zP
        The serialized form of a self-closing tag is C{'<tagName />'}.
        s   <img />Nr-   r&   imgr0   r2   r2   r3   test_serializeSelfClosingTagsE      z0SerializationTests.test_serializeSelfClosingTagsc                 C   s   |  tjddd dS )zV
        The serialized form of attribute I{a} with value I{b} is C{'a="b"'}.
        foosrcs   <img src="foo" />Nr7   r0   r2   r2   r3   test_serializeAttributeK   s   z*SerializationTests.test_serializeAttributec                 C   s&   t  }tddg|_| |d dS )zg
        Multiple attributes are separated by a single space in their serialized
        form.
        )r=   r;   )namebars   <img src="foo" name="bar" />N)r&   r8   r   
attributesr-   r1   tagr2   r2   r3   !test_serializedMultipleAttributesQ   s   z4SerializationTests.test_serializedMultipleAttributeswrapDatawrapTagc                 C   s    |  |tj|ddd dS )a  
        Common implementation of L{test_serializedAttributeWithSanitization}
        and L{test_serializedDeferredAttributeWithSanitization},
        L{test_serializedAttributeWithTransparentTag}.

        @param wrapData: A 1-argument callable that wraps around the
            attribute's value so other tests can customize it.

        @param wrapTag: A 1-argument callable that wraps around the outer tag
            so other tests can customize it.
        <>&"r<   s!   <img src="&lt;&gt;&amp;&quot;" />Nr7   )r1   rE   rF   r2   r2   r3   checkAttributeSanitizationZ   s   z-SerializationTests.checkAttributeSanitizationc                 C   s   |  tt dS )z
        Attribute values containing C{"<"}, C{">"}, C{"&"}, or C{'"'} have
        C{"&lt;"}, C{"&gt;"}, C{"&amp;"}, or C{"&quot;"} substituted for those
        bytes in the serialized output.
        N)rH   r   r0   r2   r2   r3   (test_serializedAttributeWithSanitizationo      z;SerializationTests.test_serializedAttributeWithSanitizationc                 C   s   |  tt dS )z
        Like L{test_serializedAttributeWithSanitization}, but when the contents
        of the attribute are in a L{Deferred
        <twisted.internet.defer.Deferred>}.
        N)rH   r   r   r0   r2   r2   r3   0test_serializedDeferredAttributeWithSanitizationw   rJ   zCSerializationTests.test_serializedDeferredAttributeWithSanitizationc                    s@   g  dt dtf fdd}dtdtf fdd}| || dS )	zS
        Like L{test_serializedAttributeWithSanitization} but with a slot.
        valuer)   c                    s     |  tdS )Nstuff)appendr%   rL   tossr2   r3   
insertSlot   s   
zWSerializationTests.test_serializedAttributeWithSlotWithSanitization.<locals>.insertSlotrC   c                    s   | j   dS )N)rM   )	fillSlotspoprC   rP   r2   r3   fillSlot   s   zUSerializationTests.test_serializedAttributeWithSlotWithSanitization.<locals>.fillSlotN)strr    r!   rH   )r1   rR   rV   r2   rP   r3   0test_serializedAttributeWithSlotWithSanitization   s   zCSerializationTests.test_serializedAttributeWithSlotWithSanitizationc                 C   s   |  tjt dS )z
        Attribute values which are supplied via the value of a C{t:transparent}
        tag have the same substitution rules to them as values supplied
        directly.
        N)rH   r&   transparentr   r0   r2   r2   r3   *test_serializedAttributeWithTransparentTag   s   z=SerializationTests.test_serializedAttributeWithTransparentTagc                    sR   G dd dt  g dtdtffdd}dtdtf fdd	}| || d
S )z
        Like L{test_serializedAttributeWithTransparentTag}, but when the
        attribute is rendered by a renderer on an element.
        c                       sH   e Zd Zdedee f fddZedee de	de
fdd	Z  ZS )
z_SerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRendererrL   loaderc                    s   || _ t | d S N)rL   super__init__)r1   rL   r[   	__class__r2   r3   r^      s   zhSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRenderer.__init__requestrC   r)   c                 S      | j S r\   rO   )r1   ra   rC   r2   r2   r3   rM      s   zeSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRenderer.stuff)__name__
__module____qualname__rW   r
   r   r^   r$   r   r!   r    rM   __classcell__r2   r2   r_   r3   WithRenderer   s    $rg   rL   r)   c                    s     |  tjddS )NrM   render)rN   r&   rY   rO   rP   r2   r3   insertRenderer   s   
zaSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.insertRendererrC   c                    s      t| S r\   )rT   r"   rU   rg   rQ   r2   r3   ri      s   zYSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.renderN)r   rW   r    r!   rH   )r1   rj   ri   r2   rk   r3   6test_serializedAttributeWithTransparentTagWithRenderer   s
   	zISerializationTests.test_serializedAttributeWithTransparentTagWithRendererc                 C   s&   t tG dd d}| |t dS )z
        Like L{test_serializedAttributeWithTransparentTag}, but when the
        attribute is a provider of L{IRenderable} rather than a transparent
        tag.
        c                   @   sR   e Zd ZdefddZdee defddZdede	ee e
gef fd	d
ZdS )zLSerializationTests.test_serializedAttributeWithRenderable.<locals>.ArbitraryrL   c                 S   s
   || _ d S r\   rO   )r1   rL   r2   r2   r3   r^         
zUSerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitrary.__init__ra   r)   c                 S   rb   r\   rO   r1   ra   r2   r2   r3   ri      s   zSSerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitrary.renderr?   c                 S      t d)NzUnexpected call)NotImplementedErrorr1   r?   r2   r2   r3   lookupRenderMethod   s   z_SerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitrary.lookupRenderMethodN)rc   rd   re   r    r^   r
   r   ri   rW   r   r!   rr   r2   r2   r2   r3   	Arbitrary   s    rs   N)r   r   rH   r   )r1   rs   r2   r2   r3   &test_serializedAttributeWithRenderable   s   z9SerializationTests.test_serializedAttributeWithRenderablec                 C   sL   t d}t j||d}| |d}| |d}| t|jd | dS )ag  
        Common implementation of L{test_serializedAttributeWithTag} and
        L{test_serializedAttributeWithDeferredTag}.

        @param wrapTag: A 1-argument callable that wraps around the attribute's
            value so other tests can customize it.
        @type wrapTag: callable taking L{Tag} and returning something
            flattenable
        rG   r<   s@   <img src="&lt;a&gt;&amp;lt;&amp;gt;&amp;amp;&quot;&lt;/a&gt;" />s   <a>&lt;&gt;&amp;"</a>r=   N)r&   ar8   r-   assertXMLEqualr   attrib)r1   rF   innerTagouterTagouterinnerr2   r2   r3   checkTagAttributeSerialization   s   
z1SerializationTests.checkTagAttributeSerializationc                 C      |  t dS )z
        L{Tag} objects which are serialized within the context of an attribute
        are serialized such that the text content of the attribute may be
        parsed to retrieve the tag.
        N)r|   r   r0   r2   r2   r3   test_serializedAttributeWithTag   s   z2SerializationTests.test_serializedAttributeWithTagc                 C   r}   )z
        Like L{test_serializedAttributeWithTag}, but when the L{Tag} is in a
        L{Deferred <twisted.internet.defer.Deferred>}.
        N)r|   r   r0   r2   r2   r3   'test_serializedAttributeWithDeferredTag   s   z:SerializationTests.test_serializedAttributeWithDeferredTagc                 C   s6   |  tjtjdddd}| t|jd d dS )z
        Similar to L{test_serializedAttributeWithTag}, but for the additional
        complexity where the tag which is the attribute value itself has an
        attribute value which contains bytes which require substitution.
        rG   )hrefr<   sV   <img src="&lt;a href=&quot;&amp;lt;&amp;gt;&amp;amp;&amp;quot;&quot;&gt;&lt;/a&gt;" />r=   s"   <a href="&lt;&gt;&amp;&quot;"></a>N)r-   r&   r8   ru   rv   r   rw   )r1   	flattenedr2   r2   r3   ,test_serializedAttributeWithTagWithAttribute   s   z?SerializationTests.test_serializedAttributeWithTagWithAttributec                 C      |  tdd dS )zI
        Test that comments are correctly flattened and escaped.
        foo bars   <!--foo bar-->N)r-   r   r0   r2   r2   r3   test_serializeComment  r:   z(SerializationTests.test_serializeCommentc                    sN   dt ddf fdd}g }dD ]}tdt|}|| || qt|S )a  
        The data in a L{Comment} is escaped and mangled in the flattened output
        so that the result is a legal SGML and XML comment.

        SGML comment syntax is complicated and hard to use. This rule is more
        restrictive, and more compatible:

        Comments start with <!-- and end with --> and never contain -- or >.

        Also by XML syntax, a comment may not end with '-'.

        @see: U{http://www.w3.org/TR/REC-xml/#sec-comments}
        cr)   Nc                    s     | d| d   | d| d   t| dk| d | dd } d	|  d
| |rC |d d d S d S )Ns   <!--z' does not start with the comment prefixs   -->z% does not end with the comment suffix   z# is too short to be a legal comment   s   --   >   -)
assertTrue
startswithendswithlenassertNotInassertNotEqual)r   contentr0   r2   r3   verifyComment  s   z>SerializationTests.test_commentEscaping.<locals>.verifyComment) z	foo---barz
foo---bar-zfoo>barz	foo-->barz----------------)bytesr#   r   addCallbackrN   r   )r1   r   resultsr   dr2   r0   r3   test_commentEscaping  s   
z'SerializationTests.test_commentEscapingc                 C   s&   |  tddf |  tdd dS )zE
        Test that CDATA is correctly flattened and escaped.
        r   s   <![CDATA[foo bar]]>zfoo ]]> bars#   <![CDATA[foo ]]]]><![CDATA[> bar]]>N)r-   r   r0   r2   r2   r3   test_serializeCDATA6  s   z&SerializationTests.test_serializeCDATAc                 C   sn   d}|  |d |  t|d |  t|d |  t|d | t|t | td|didt d	S )
z
        Test that unicode is encoded correctly in the appropriate places, and
        raises an error when it occurs in inappropriate place.
           ☃s   ☃s
   <p>☃</p>s
   <!--☃-->s   <![CDATA[☃]]>pr   )rA   N)r-   r&   r   r   r   assertFlatteningRaisesr!   UnicodeEncodeError)r1   snowmanr2   r2   r3   test_serializeUnicode?  s   z(SerializationTests.test_serializeUnicodec                 C   s   t td}| |d dS )ze
        A character reference is flattened to a string using the I{&#NNNN;}
        syntax.
        r   s   &#9731;N)r   ordr-   )r1   refr2   r2   r3   test_serializeCharRefN  s   z(SerializationTests.test_serializeCharRefc                 C   r   )zz
        Test that a deferred is substituted with the current value in the
        callback chain when flattened.
        twos   twoN)r-   r   r0   r2   r2   r3   test_serializeDeferredV  s   z)SerializationTests.test_serializeDeferredc                 C   s$   t d}| |d | |d dS )zE
        Test that the same deferred can be flattened twice.
        threes   threeN)r   r-   )r1   r   r2   r2   r3   test_serializeSameDeferredTwice]  s   z2SerializationTests.test_serializeSameDeferredTwicec                 C   s:   ddl m} i }t|d| |d }| |dd dS )zt
        Test that a coroutine returning a value is substituted with the that
        value when flattened.
        r   r   zE
            async def coro(x):
                return x
            corofour   fourN)textwrapr   execr-   r1   r   	namespacer   r2   r2   r3   test_serializeCoroutinee  s   	z*SerializationTests.test_serializeCoroutinec                 C   s@   ddl m} ttd}t|d| |d }| |dd dS )	z
        Test that a coroutine returning an awaited deferred value is
        substituted with that value when flattened.
        r   r   )r   zT
            async def coro(x):
                return await succeed(x)
            r   r   r   N)r   r   dictr   r   r-   r   r2   r2   r3    test_serializeCoroutineWithAwaitz  s   
	z3SerializationTests.test_serializeCoroutineWithAwaitc                    s,   t tG  fddd} | d dS )zQ
        Test that flattening respects all of the IRenderable interface.
        c                       sD   e Zd ZdedefddZdedeee	 ege
f f fddZdS )	zASerializationTests.test_serializeIRenderable.<locals>.FakeElementoredr)   c                 S   s    t dt jdddt jddS )Nzhello, testrh   z - )r&   r   rY   )ignr   r2   r2   r3   ri     s   

zHSerializationTests.test_serializeIRenderable.<locals>.FakeElement.renderr?   c                    s     |d dd S )Nr   c                 S   s   |dS )Nworldr2   )r   noder2   r2   r3   <lambda>  s    zfSerializationTests.test_serializeIRenderable.<locals>.FakeElement.lookupRenderMethod.<locals>.<lambda>)assertEqual)r   r?   r0   r2   r3   rr     s   zTSerializationTests.test_serializeIRenderable.<locals>.FakeElement.lookupRenderMethodN)rc   rd   re   objectr!   ri   rW   r   r
   r   r    rr   r2   r0   r2   r3   FakeElement  s    r   s   <p>hello, world - world</p>N)r   r   r-   )r1   r   r2   r0   r3   test_serializeIRenderable  s   z,SerializationTests.test_serializeIRenderablec                 C   s   |  tjddt dS )z
        Test that flattening a tag with a C{render} attribute when no render
        factory is available in the context raises an exception.
        r   rh   N)r   r&   rY   
ValueErrorr0   r2   r2   r3   "test_serializeMissingRenderFactory  s   z5SerializationTests.test_serializeMissingRenderFactoryc                 C   s>   t td}| }|jdd | |t | |d dS )zS
        Test that flattening a slot will use the slot value from the tag.
        r   zhello, worldr   s   <p>hello, world</p>N)r&   r   r%   clonerS   r   r   r-   )r1   t1t2r2   r2   r3   test_serializeSlots  s
   z&SerializationTests.test_serializeSlotsc                 C   s4   t td}|jtt dd | |d dS )z|
        Test that a slot with a deferred as its value will be flattened using
        the value from the deferred.
        r   zfour>r   s   <p><em>four&gt;</em></p>N)r&   r   r%   rS   r   emr-   )r1   tr2   r2   r3   test_serializeDeferredSlots  s   z.SerializationTests.test_serializeDeferredSlotsc                 C   s   |  dt dS )zT
        Test that flattening an unknown type of thing raises an exception.
        N)r   r   r0   r2   r2   r3   test_unknownTypeRaises  s   z)SerializationTests.test_unknownTypeRaisesr)   N))rc   rd   re   __doc__r4   r6   r9   r>   rD   r   rW   r    r!   rH   rI   rK   rX   rZ   rl   rt   r|   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r2   r2   r2   r3   r(   0   sT    

	


	












/
	









	r(   c                   C      d S r\   r2   r2   r2   r2   r3   r     s    r   c                   @   sL   e Zd ZdZdddZdddZddd	Zdd
dZdddZdddZ	dS )FlattenerErrorTestsz&
    Tests for L{FlattenerError}.
    r)   Nc                 C   s:   t tG dd d}| tttd| gg d dS )z
        If a L{FlattenerError} is created with an L{IRenderable} provider root,
        the repr of that object is included in the string representation of the
        exception.
        c                   @   s   e Zd ZdefddZdS )z7FlattenerErrorTests.test_renderable.<locals>.Renderabler)   c                 S      dS )Nzrenderable reprr2   r0   r2   r2   r3   __repr__     z@FlattenerErrorTests.test_renderable.<locals>.Renderable.__repr__N)rc   rd   re   rW   r   r2   r2   r2   r3   
Renderable  s    r   reasonzCException while flattening:
  renderable repr
RuntimeError: reason
N)r   r   r   rW   r   RuntimeError)r1   r   r2   r2   r3   test_renderable  s   z#FlattenerErrorTests.test_renderablec                 C   s2   t ddddd}| tttd|gg d dS )	z
        If a L{FlattenerError} is created with a L{Tag} instance with source
        location information, the source location is included in the string
        representation of the exception.
        divz/foo/filename.xhtml      )filename
lineNumbercolumnNumberr   zlException while flattening:
  File "/foo/filename.xhtml", line 17, column 12, in "div"
RuntimeError: reason
N)r!   r   rW   r   r   rB   r2   r2   r3   test_tag  s
   zFlattenerErrorTests.test_tagc                 C   s&   |  tttdtdgg d dS )z
        If a L{FlattenerError} is created with a L{Tag} instance without source
        location information, only the tagName is included in the string
        representation of the exception.
        r   spanz>Exception while flattening:
  Tag <span>
RuntimeError: reason
N)r   rW   r   r   r!   r0   r2   r2   r3   test_tagWithoutLocation  s   z+FlattenerErrorTests.test_tagWithoutLocationc              
      s   d fdd}dt fdd z|  W n! ty4 } ztt d dd }|}W Y d}~n
d}~ww | d	 | tt	|g |d
t
|jjd t
 jjd f  dS )z
        If a L{FlattenerError} is created with traceback frames, they are
        included in the string representation of the exception.
        r)   Nc                      s
      d S r\   r2   r2   gr2   r3   f  rm   z-FlattenerErrorTests.test_traceback.<locals>.fc                   S   ro   )Nr   )r   r2   r2   r2   r3   r     s   z-FlattenerErrorTests.test_traceback.<locals>.g      zf() must raise RuntimeErrorzException while flattening:
  File "%s", line %d, in f
    g()
  File "%s", line %d, in g
    raise RuntimeError("reason")
RuntimeError: reason
r   )r	   r   	traceback
extract_tbsysexc_infofailr   rW   r   HERE__code__co_firstlineno)r1   r   etbinfoexcr2   r   r3   test_traceback  s(   



z"FlattenerErrorTests.test_tracebackc                    s   t   ttG  fddd}td| g}| | td} | | |t}| 	t
|jtjtdtjd |  t dS )z
        When flattening a renderer which raises an exception asynchronously,
        the error is reported when it occurs.
        c                       sZ   e Zd ZdZdefddZdedeee e	ge
f fddZdee de
f fd	d
ZdS )zPFlattenerErrorTests.test_asynchronousFlattenError.<locals>.NotActuallyRenderablez#No methods provided; this will failr)   c                 S   r   )Nz<unrenderable>r2   r0   r2   r2   r3   r   6  r   zYFlattenerErrorTests.test_asynchronousFlattenError.<locals>.NotActuallyRenderable.__repr__r?   c                 S   r   r\   r2   rq   r2   r2   r3   rr   9  s   zcFlattenerErrorTests.test_asynchronousFlattenError.<locals>.NotActuallyRenderable.lookupRenderMethodra   c                    s    S r\   r2   rn   failingr2   r3   ri   >  r   zWFlattenerErrorTests.test_asynchronousFlattenError.<locals>.NotActuallyRenderable.renderN)rc   rd   re   r   rW   r   r   r
   r   r!   r    rr   ri   r2   r   r2   r3   NotActuallyRenderable2  s    
r   Nexamplea@                      Exception while flattening:
                      \[<unrenderable>\]
                      <unrenderable>
                      .*
                      File ".*", line \d*, in _flattenTree
                        element = await element
                    RuntimeError: example
                    )flags)r   r   r   r#   assertNoResultr   errbackfailureResultOfr   assertRegexrW   rL   recompiler   	MULTILINE)r1   r   
flatteningr   failurer2   r   r3   test_asynchronousFlattenError+  s$   

z1FlattenerErrorTests.test_asynchronousFlattenErrorc                    s   dd dt t ddf fdd}ddtddffdd	}t |}td|}| | || |  | |t}| 	d
 | 
 | | t | ttjt |jjd }| |t dS )z@
        The flattening of a Deferred can be cancelled.
        r   N	cancelledr)   c                    s   |  d7 d S )Nr   r2   )r   )	cancelArgcancelCountr2   r3   checkCancelb  s   z4FlattenerErrorTests.test_cancel.<locals>.checkCancelr   c                    s   |  d S r\   r2   )r   )errr2   r3   saveErri  s   z0FlattenerErrorTests.test_cancel.<locals>.saveErrr   )r   r   r   r#   r   
addErrbackcancelr   r   r   assertIsassertIsInstancer   rL   r   args)r1   r   r  r   r   r   r   r2   )r   r   r   r3   test_cancel[  s"   


zFlattenerErrorTests.test_cancelr   )
rc   rd   re   r   r   r   r   r   r   r  r2   r2   r2   r3   r     s    




&0r   )<r   r   r   r   collectionsr   r   r   typesr   typingr   r   r   r	   r
   r   xml.etree.ElementTreer   zope.interfacer   twisted.internet.deferr   r   r   r   r   twisted.python.failurer   twisted.test.testutilsr   twisted.trial.unittestr   twisted.web.errorr   r   r   twisted.web.iwebr   r   r   twisted.web.templater   r   r   r   r    r!   r"   r#   r$   r%   r&   twisted.web.test._utilr'   r(   r   co_filenamer   r   r2   r2   r2   r3   <module>   s0    4   #