U
    
W[SG                     @   s  d 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
 ddlmZ ddlmZ dd	lmZmZ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mZmZmZ ddlm Z m!Z!m"Z"m#Z# ddl$m%Z% G dd de%eZ&dd j'j(Z)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)XML)OrderedDict)implementer)	_PY35PLUS)TestCase)XMLAssertionMixin)passthrusucceedgatherResults)IRenderable)UnfilledSlotUnsupportedTypeFlattenerError)tagsTagCommentCDATACharRefslot)Elementrenderer	TagLoaderflattenString)FlattenTestCasec                   @   s  e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zesd2e_d3d4 Zesd2e_d5d6 Zd7d8 Z d9d: Z!d;d< Z"d=S )>SerializationTestsz.
    Tests for flattening various things.
    c                 C   s   |  tjtddddS )z:
        Test that nested tags flatten correctly.
        Z42Zthere)his'   <html hi="there"><body>42</body></html>)assertFlattensTor   ZhtmlZbodyself r   ?/usr/lib/python3/dist-packages/twisted/web/test/test_flatten.pytest_nestedTags'   s    z"SerializationTests.test_nestedTagsc                 C   s   t | dd| ddgS )zL
        Test that strings will be flattened and escaped correctly.
        Zones   onez
<abc&&>123s   &lt;abc&amp;&amp;&gt;123)r
   r   r   r   r   r    test_serializeString0   s    

z'SerializationTests.test_serializeStringc                 C   s   |  t dS )zP
        The serialized form of a self-closing tag is C{'<tagName />'}.
        s   <img />)r   r   imgr   r   r   r    test_serializeSelfClosingTags:   s    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" />NassertFlattensImmediatelyr   r#   r   r   r   r    test_serializeAttributeA   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%   )nameZbars   <img src="foo" name="bar" />N)r   r#   r   
attributesr)   r   tagr   r   r    !test_serializedMultipleAttributesI   s    z4SerializationTests.test_serializedMultipleAttributesc                 C   s    |  |tj|ddd dS )au  
        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 wrapData: callable taking L{bytes} and returning something
            flattenable

        @param wrapTag: A 1-argument callable that wraps around the outer tag
            so other tests can customize it.
        @type wrapTag: callable taking L{Tag} and returning L{Tag}.
        <>&"r&   s!   <img src="&lt;&gt;&amp;&quot;" />Nr(   )r   ZwrapDatawrapTagr   r   r    checkAttributeSanitizationS   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)r2   r   r   r   r   r    (test_serializedAttributeWithSanitizationg   s    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)r2   r	   r   r   r   r   r    0test_serializedDeferredAttributeWithSanitizationp   s    zCSerializationTests.test_serializedDeferredAttributeWithSanitizationc                    s$   g  |   fdd fdd dS )zS
        Like L{test_serializedAttributeWithSanitization} but with a slot.
        c                    s     | ptdS )Nstuff)appendr   valuetossr   r    <lambda>       zUSerializationTests.test_serializedAttributeWithSlotWithSanitization.<locals>.<lambda>c                    s   | j   dS )N)r5   )	fillSlotspopr.   r9   r   r    r;      r<   N)r2   r   r   r9   r    0test_serializedAttributeWithSlotWithSanitizationy   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)r2   r   transparentr   r   r   r   r    *test_serializedAttributeWithTransparentTag   s    z=SerializationTests.test_serializedAttributeWithTransparentTagc                    s:   G  fdddt  g | fdd fdd dS )z
        Like L{test_serializedAttributeWithTransparentTag}, but when the
        attribute is rendered by a renderer on an element.
        c                       s*   e Zd Z fddZedd Z  ZS )z_SerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRendererc                    s   || _ t | | d S N)r8   super__init__)r   r8   loader)WithRenderer	__class__r   r    rE      s    zhSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRenderer.__init__c                 S   s   | j S rC   r7   )r   requestr.   r   r   r    r5      s    zeSerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.WithRenderer.stuff)__name__
__module____qualname__rE   r   r5   __classcell__r   )rG   )rH   r    rG      s   rG   c                    s     | ptjddS )Nr5   render)r6   r   rA   r7   r9   r   r    r;      s   
z[SerializationTests.test_serializedAttributeWithTransparentTagWithRenderer.<locals>.<lambda>c                    s      t| S rC   )r>   r   r?   rG   r:   r   r    r;      r<   N)r   r2   r   r   rP   r    6test_serializedAttributeWithTransparentTagWithRenderer   s    
zISerializationTests.test_serializedAttributeWithTransparentTagWithRendererc                 C   s(   t tG dd dt}| |t dS )z
        Like L{test_serializedAttributeWithTransparentTag}, but when the
        attribute is a provider of L{IRenderable} rather than a transparent
        tag.
        c                   @   s   e Zd Zdd Zdd ZdS )zLSerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitraryc                 S   s
   || _ d S rC   r7   )r   r8   r   r   r    rE      s    zUSerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitrary.__init__c                 S   s   | j S rC   r7   )r   rI   r   r   r    rO      s    zSSerializationTests.test_serializedAttributeWithRenderable.<locals>.Arbitrary.renderN)rJ   rK   rL   rE   rO   r   r   r   r    	Arbitrary   s   rR   N)r   r   objectr2   r   )r   rR   r   r   r    &test_serializedAttributeWithRenderable   s    z9SerializationTests.test_serializedAttributeWithRenderablec                 C   sL   t d}t j||d}| |d}| |d}| t|jd | dS )ah  
        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.
        @param wrapTag: callable taking L{Tag} and returning something
            flattenable
        r0   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   ar#   r)   assertXMLEqualr   attrib)r   r1   ZinnerTagZouterTagZouterinnerr   r   r    checkTagAttributeSerialization   s    

 z1SerializationTests.checkTagAttributeSerializationc                 C   s   |  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)rY   r   r   r   r   r    test_serializedAttributeWithTag   s    z2SerializationTests.test_serializedAttributeWithTagc                 C   s   |  t dS )z
        Like L{test_serializedAttributeWithTag}, but when the L{Tag} is in a
        L{Deferred <twisted.internet.defer.Deferred>}.
        N)rY   r	   r   r   r   r    '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.
        r0   )Z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   r#   rU   rV   r   rW   )r   Z	flattenedr   r   r    ,test_serializedAttributeWithTagWithAttribute   s    z?SerializationTests.test_serializedAttributeWithTagWithAttributec                 C   s   |  tddfS )zI
        Test that comments are correctly flattened and escaped.
        foo bars   <!--foo bar-->)r   r   r   r   r   r    test_serializeComment   s    z(SerializationTests.test_serializeCommentc                    sD    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}
        c                    s     | dd| f    | dd| f    t| dkd| f  | dd } d	|  d
| |r |d d d S )Ns   <!--z)%r does not start with the comment prefixs   -->z'%r does not end with the comment suffix   z%%r is too short to be a legal comment   s   --   >   -)Z
assertTrue
startswithendswithlenZassertNotInZassertNotEqual)cZcontentr   r   r    verifyComment   s"    
z>SerializationTests.test_commentEscaping.<locals>.verifyComment) z	foo---barz
foo---bar-zfoo>barz	foo-->barz----------------N)r   r   ZaddCallbackr6   r
   )r   ri   Zresultsrh   dr   r   r    test_commentEscaping   s    
z'SerializationTests.test_commentEscapingc                 C   s$   t | tdd| tddgS )zE
        Test that CDATA is correctly flattened and escaped.
        r]   s   <![CDATA[foo bar]]>zfoo ]]> bars#   <![CDATA[foo ]]]]><![CDATA[> bar]]>)r
   r   r   r   r   r   r    test_serializeCDATA!  s    z&SerializationTests.test_serializeCDATAc                 C   sf   d}t | |d| t|d| t|d| t|d| t|t| td|didtg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[☃]]>prj   )r,   )	r
   r   r   ro   r   r   assertFlatteningRaisesr   UnicodeEncodeError)r   Zsnowmanr   r   r    test_serializeUnicode-  s    
  z(SerializationTests.test_serializeUnicodec                 C   s   t td}| |dS )ze
        A character reference is flattened to a string using the I{&#NNNN;}
        syntax.
        rn   s   &#9731;)r   ordr   )r   refr   r   r    test_serializeCharRef?  s    z(SerializationTests.test_serializeCharRefc                 C   s   |  tddS )zz
        Test that a deferred is substituted with the current value in the
        callback chain when flattened.
        Ztwos   two)r   r	   r   r   r   r    test_serializeDeferredH  s    z)SerializationTests.test_serializeDeferredc                 C   s$   t d}t| |d| |dgS )zE
        Test that the same deferred can be flattened twice.
        Zthrees   three)r	   r
   r   )r   rk   r   r   r    test_serializeSameDeferredTwiceP  s
    

z2SerializationTests.test_serializeSameDeferredTwicec                 C   s6   ddl m} i }t|d| |d }| |ddS )zt
        Test that a coroutine returning a value is substituted with the that
        value when flattened.
        r   dedentzE
            async def coro(x):
                return x
            corofour   four)textwrapry   execr   r   ry   	namespacerz   r   r   r    test_serializeCoroutine[  s    z*SerializationTests.test_serializeCoroutinez*coroutines not available before Python 3.5c                 C   s<   ddl m} ttd}t|d| |d }| |ddS )z
        Test that a coroutine returning an awaited deferred value is
        substituted with that value when flattened.
        r   rx   )r	   zT
            async def coro(x):
                return await succeed(x)
            rz   r{   r|   )r}   ry   dictr	   r~   r   r   r   r   r     test_serializeCoroutineWithAwaitr  s    
z3SerializationTests.test_serializeCoroutineWithAwaitc                    s0   t tG  fdddt}t | dgS )zQ
        Test that flattening respects all of the IRenderable interface.
        c                       s    e Zd Zdd Z fddZdS )zASerializationTests.test_serializeIRenderable.<locals>.FakeElementc                 S   s    t dt jdddt jddS )Nzhello, testrN   z - )r   ro   rA   )ignZoredr   r   r    rO     s    
 
zHSerializationTests.test_serializeIRenderable.<locals>.FakeElement.renderc                    s     |d dd S )Nr   c                 S   s   |dS )NZworldr   )r   Znoder   r   r    r;     r<   zfSerializationTests.test_serializeIRenderable.<locals>.FakeElement.lookupRenderMethod.<locals>.<lambda>)assertEqual)r   r+   r   r   r    lookupRenderMethod  s    zTSerializationTests.test_serializeIRenderable.<locals>.FakeElement.lookupRenderMethodN)rJ   rK   rL   rO   r   r   r   r   r    FakeElement  s   r   s   <p>hello, world - world</p>)r   r   rS   r
   r   )r   r   r   r   r    test_serializeIRenderable  s
    
z,SerializationTests.test_serializeIRenderablec                 C   s>   t td}| }|jdd t| |t| |dg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>)	r   ro   r   Zcloner=   r
   rp   r   r   )r   t1t2r   r   r    test_serializeSlots  s    

z&SerializationTests.test_serializeSlotsc                 C   s0   t td}|jtt 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>)r   ro   r   r=   r	   Zemr   )r   tr   r   r    test_serializeDeferredSlots  s    z.SerializationTests.test_serializeDeferredSlotsc                 C   s   |  dtS )zT
        Test that flattening an unknown type of thing raises an exception.
        N)rp   r   r   r   r   r    test_unknownTypeRaises  s    z)SerializationTests.test_unknownTypeRaisesN)#rJ   rK   rL   __doc__r!   r"   r$   r*   r/   r2   r3   r4   r@   rB   rQ   rT   rY   rZ   r[   r\   r^   rl   rm   rr   ru   rv   rw   r   r   skipr   r   r   r   r   r   r   r   r    r   #   sH   	

				/	
r   c                   C   s   d S rC   r   r   r   r   r    r;     r<   r;   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )FlattenerErrorTestsz&
    Tests for L{FlattenerError}.
    c                 C   s<   t tG dd dt}| 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d ZdS )z7FlattenerErrorTests.test_renderable.<locals>.Renderablec                 S   s   dS )Nzrenderable reprr   r   r   r   r    __repr__  s    z@FlattenerErrorTests.test_renderable.<locals>.Renderable.__repr__N)rJ   rK   rL   r   r   r   r   r    
Renderable  s   r   reasonzCException while flattening:
  renderable repr
RuntimeError: reason
N)r   r   rS   r   strr   RuntimeError)r   r   r   r   r    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.
        Zdivz/foo/filename.xhtml      )filenameZ
lineNumberZcolumnNumberr   zlException while flattening:
  File "/foo/filename.xhtml", line 17, column 12, in "div"
RuntimeError: reason
N)r   r   r   r   r   r-   r   r   r    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   r   r   r   r   r   r   r   r    test_tagWithoutLocation  s    z+FlattenerErrorTests.test_tagWithoutLocationc              
      s    fdd}dd  z
|  W n@ t k
r^ } z"tt d dd }|}W 5 d}~X Y nX | 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.
        c                      s
      d S rC   r   r   gr   r    f  s    z-FlattenerErrorTests.test_traceback.<locals>.fc                   S   s   t dd S )Nr   )r   r   r   r   r    r     s    z-FlattenerErrorTests.test_traceback.<locals>.g      Nz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   	traceback
extract_tbsysexc_infoZfailr   r   r   HERE__code__co_firstlineno)r   r   eZtbinfoexcr   r   r    test_traceback  s$    

 
 
z"FlattenerErrorTests.test_tracebackN)rJ   rK   rL   r   r   r   r   r   r   r   r   r    r     s
   r   )+r   r   r   Zxml.etree.cElementTreer   collectionsr   Zzope.interfacer   Ztwisted.python.compatr   Ztwisted.trial.unittestr   Ztwisted.test.testutilsr   Ztwisted.internet.deferr   r	   r
   Ztwisted.web.iwebr   Ztwisted.web.errorr   r   r   Ztwisted.web.templater   r   r   r   r   r   r   r   r   r   Ztwisted.web.test._utilr   r   r   co_filenamer   r   r   r   r   r    <module>   s(       #