U
    ˆj'9  ã                   @  s  d dl m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
m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„ Zdd„ Zdd„ ZG dd„ deƒZG dd„ dƒZddœdd„Zeeƒ  dƒeeƒ  dƒG dd„ de
ƒƒƒZeG dd„ deƒƒZd d!„ Zd"d#„ Zeeƒ  dƒeeƒ  dƒG d$d%„ d%e
ƒƒƒZ eeƒ  dƒeeƒ  d&ƒeeƒ  dƒG d'd(„ d(e
ƒƒƒƒZ!eeƒ  dƒeeƒ  dƒG d)d*„ d*e
ƒƒƒZ"G d+d,„ d,eƒZ#G d-d.„ d.eƒZ$G d/d0„ d0eƒZ%eeƒ  dƒeeƒ  d&ƒeeƒ  dƒG d1d2„ d2e
ƒƒƒƒZ&dS )3é    )ÚannotationsN)Ú	dataclass)ÚProtocol)ÚTestCaseÚskipIf)ÚTypeMachineBuilderÚpep614é   )ÚMethodicalMachine)ÚTypeMachineé   )ÚisTwistedInstalledc                   C  s,   zt dƒ W n tk
r"   Y dS X dS dS )z2
    Is the graphviz Python module installed?
    ZgraphvizFTN)Ú
__import__ÚImportError© r   r   ú@/tmp/pip-unpacked-wheel-09g3rnyj/automat/_test/test_visualize.pyÚisGraphvizModuleInstalled   s
    r   c               	   C  s>   t  ¡ \} }t  |¡ ztjd| dd� W ¢S t  | ¡ X dS )z+
    Are the graphviz tools installed?
    ÚdotT)ÚstdinÚshellN)ÚosÚpipeÚcloseÚ
subprocessÚcall)ÚrÚwr   r   r   ÚisGraphvizInstalled   s
    
r   c                    s,   t ƒ ‰ G ‡ fdd„dtƒ} | ƒ }| ¡  ˆ S )zG
    Create a sample L{MethodicalMachine} with some sample states.
    c                      s`   e Zd Z” jdd�dd„ ƒZ”  ¡ dd„ ƒZ”  ¡ dd„ ƒZ”  ¡ d	d
„ ƒZ	e 
eee	g¡ dS )z#sampleMachine.<locals>.SampleObjectT)Úinitialc                 S  s   dS )zinitial stateNr   ©Úselfr   r   r   Úbegin0   s    z)sampleMachine.<locals>.SampleObject.beginc                 S  s   dS )z	end stateNr   r   r   r   r   Úend4   s    z'sampleMachine.<locals>.SampleObject.endc                 S  s   dS )zsample inputNr   r   r   r   r   Úgo8   s    z&sampleMachine.<locals>.SampleObject.goc                 S  s   dS )zsample outputNr   r   r   r   r   Úout<   s    z'sampleMachine.<locals>.SampleObject.outN)Ú__name__Ú
__module__Ú__qualname__Ústater!   r"   Úinputr#   Úoutputr$   Úuponr   ©Úmmr   r   ÚSampleObject/   s   




r.   )r
   Úobjectr#   )r.   Úsor   r,   r   ÚsampleMachine)   s
    r1   c                   @  s   e Zd Zddœdd„ZdS )ÚSampleÚNone©Úreturnc                 C  s   d S ©Nr   r   r   r   r   r#   H   ó    z	Sample.goN)r%   r&   r'   r#   r   r   r   r   r2   G   s   r2   c                   @  s   e Zd ZdS )ÚCoreN)r%   r&   r'   r   r   r   r   r8   I   s    r8   zTypeMachine[Sample, Core]r4   c                  C  sœ   t ttƒ} |  d¡}ddddœdd„}|  d|¡}|  d	¡}| tj¡ |¡ d
¡ | tj¡ |¡ d
¡ t| tj¡ |¡ƒddddœdd„ƒ}|  	¡ S )zA
    Create a sample L{TypeMachine} with some sample states.
    r!   r2   r8   Úint)ÚprotoÚcorer5   c                 S  s   dS )Né   r   )r:   r;   r   r   r   ÚbuilditS   s    z"sampleTypeMachine.<locals>.builditÚdatar"   Nr3   )Úsampler;   r5   c                 S  s   d S r6   r   )r?   r;   r   r   r   r$   [   s    zsampleTypeMachine.<locals>.out)
r   r2   r8   r(   r+   r#   ÚtoZreturnsr   Úbuild)Zbuilderr!   r=   r>   r"   r$   r   r   r   ÚsampleTypeMachineL   s    


rB   z!Graphviz module is not installed.zTwisted is not installed.c                   @  s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚElementMakerTestszL
    L{elementMaker} generates HTML representing the specified element.
    c                 C  s   ddl m} || _d S )Nr	   )ÚelementMaker)Ú
_visualizerD   )r    rD   r   r   r   ÚsetUph   s    zElementMakerTests.setUpc              	   C  s"   d}|   || jddddd�¡ dS )zK
        L{elementMaker} orders HTML attributes lexicographically.
        z<div a="1" b="2" c="3"></div>ÚdivÚ2Ú1Ú3©ÚbÚaÚcN©ÚassertEqualrD   ©r    Úexpectedr   r   r   Útest_sortsAttrsm   s    z!ElementMakerTests.test_sortsAttrsc              	   C  s"   d}|   || jddddd�¡ dS )z¡
        L{elementMaker} quotes HTML attributes according to DOT's quoting rule.

        See U{http://www.graphviz.org/doc/info/lang.html}, footnote 1.
        z-<div a="1" b="a \" quote" c="a string"></div>rG   z	a " quoter   za stringrK   NrO   rQ   r   r   r   Útest_quotesAttrst   s
     ÿz"ElementMakerTests.test_quotesAttrsc                 C  s   d}|   ||  d¡¡ dS )zN
        L{elementMaker} should render an element with no attributes.
        z<div ></div>rG   NrO   rQ   r   r   r   Útest_noAttrs   s    zElementMakerTests.test_noAttrsN)r%   r&   r'   Ú__doc__rF   rS   rT   rU   r   r   r   r   rC   a   s
   rC   c                   @  s*   e Zd ZU dZded< ded< ded< dS )	ÚHTMLElementz2Holds an HTML element, as created by elementMaker.ÚstrÚnamezlist[HTMLElement]Úchildrenzdict[str, str]Ú
attributesN)r%   r&   r'   rV   Ú__annotations__r   r   r   r   rW   ‡   s   
rW   c                   s.   ˆ | ƒr| gS t | ƒrg S ‡ fdd„| jD ƒS )zk
    Recursively collect all elements in an L{HTMLElement} tree that
    match the optional predicate.
    c                   s    g | ]}t |ˆ ƒD ]}|‘qqS r   )ÚfindElements)Ú.0ÚchildÚresult©Ú	predicater   r   Ú
<listcomp>š   s    þz findElements.<locals>.<listcomp>)ÚisLeafrZ   )Úelementrb   r   ra   r   r]   �   s    
þr]   c                 C  s   t | tƒ S )z2
    This HTML element is actually leaf node.
    )Ú
isinstancerW   ©re   r   r   r   rd   ¡   s    rd   c                   @  s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )ÚTableMakerTestszÚ
    Tests that ensure L{tableMaker} generates HTML tables usable as
    labels in DOT graphs.

    For more information, read the "HTML-Like Labels" section of
    U{http://www.graphviz.org/doc/info/shapes.html}.
    c                 O  s   t |||d�S )N)rY   rZ   r[   )rW   )r    rY   rZ   r[   r   r   r   ÚfakeElementMaker³   s    z TableMakerTests.fakeElementMakerc                 C  s.   ddl m} d| _d| _tj|| jd�| _d S )Nr	   )Ú
tableMakerúinput labelzthe port)Z_E)rE   rj   Ú
inputLabelÚportÚ	functoolsÚpartialri   )r    rj   r   r   r   rF   ¶   s    zTableMakerTests.setUpc                   s’   ‡ fdd„}g dgfD ]v}ˆ j ˆ j|ˆ jd�}ˆ  t|jƒd¡ |jd }t||ƒ}ˆ  t|ƒd¡ ˆ  |d jd¡ ˆ  t|t	ƒˆ jg¡ qdS )	zÍ
        The table returned by L{tableMaker} always contains the input
        symbol label in its first row, and that row contains one cell
        with a port attribute set to the provided port.
        c                   s   t | ƒ o| j d¡ˆ jkS )Nrm   )rd   r[   Úgetrm   rg   r   r   r   ÚhasPortÄ   s    z3TableMakerTests.test_inputLabelRow.<locals>.hasPortzan output label©rm   r   r   ÚtdN)
rj   rl   rm   ZassertGreaterÚlenrZ   r]   rP   rY   rd   )r    rq   ZoutputLabelsÚtableÚinputLabelRowZportCandidatesr   r   r   Útest_inputLabelRow½   s    

z"TableMakerTests.test_inputLabelRowc                 C  s>   | j dd| jd�}|  t|jƒd¡ |j\}|  d|j¡ dS )z�
        L{tableMaker} does not add a colspan attribute to the input
        label's cell or a second row if there no output labels.
        rk   r   rr   r   ÚcolspanN)rj   rm   rP   rt   rZ   ZassertNotInr[   )r    ru   rv   r   r   r   Útest_noOutputLabelsÒ   s    z#TableMakerTests.test_noOutputLabelsc                 C  sh   | j | jd| jd�}|  t|jƒd¡ |j\}}dd„ }|  tt||ƒƒd¡ |  t|tƒddg¡ d	S )
z¹
        L{tableMaker} adds a colspan attribute to the input label's cell
        equal to the number of output labels and a second row that
        contains the output labels.
        )úoutput label 1úoutput label 2rr   r	   c                 S  s$   t | ƒ o"| jdko"| j d¡dkS )Nrs   rx   rH   )rd   rY   r[   rp   rg   r   r   r   ÚhasCorrectColspané   s
    
ÿýz@TableMakerTests.test_withOutputLabels.<locals>.hasCorrectColspanr   rz   r{   N)rj   rl   rm   rP   rt   rZ   r]   rd   )r    ru   ZinputRowZ	outputRowr|   r   r   r   Útest_withOutputLabelsÜ   s      ÿ
 ÿz%TableMakerTests.test_withOutputLabelsN)	r%   r&   r'   rV   ri   rF   rw   ry   r}   r   r   r   r   rh   ¨   s   
rh   z!Graphviz tools are not installed.c                   @  s   e Zd ZdZddœdd„ZdS )ÚIntegrationTestsz[
    Tests which make sure Graphviz can understand the output produced by
    Automat.
    r3   r4   c                 C  sN   t ƒ  ¡ }d |¡ d¡}tjdtjtjd�}| |¡\}}|  |j	d¡ dS )z8
        C{graphviz} emits valid graphviz data.
        Ú zutf-8r   )r   Ústdoutr   N)
r1   Ú	asDigraphÚjoinÚencoder   ÚPopenÚPIPEÚcommunicaterP   Ú
returncode)r    ÚdigraphÚtextÚpr$   Úerrr   r   r   Útest_validGraphvizÿ   s
    
z#IntegrationTests.test_validGraphvizN)r%   r&   r'   rV   rŒ   r   r   r   r   r~   ö   s   r~   c                   @  s    e Zd ZdZdd„ Zdd„ ZdS )Ú
SpotCheckszj
    Tests to make sure that the output contains salient features of the machine
    being generated.
    c                 C  sD   d  tƒ  ¡ ¡}|  d|¡ |  d|¡ |  d|¡ |  d|¡ dS )z‰
        The output of L{graphviz.Digraph} should contain the names of the
        states, inputs, outputs in the state machine.
        r   r!   r"   r#   r$   N)r‚   r1   r�   ÚassertIn©r    Zgvoutr   r   r   Útest_containsMachineFeatures  s
    z'SpotChecks.test_containsMachineFeaturesc                 C  sP   d  tƒ  ¡ ¡}|  d|¡ |  d|¡ |  d|¡ |  d|¡ |  d|¡ dS )z‰
        The output of L{graphviz.Digraph} should contain the names of the states,
        inputs, outputs in the state machine.
        r   r!   r"   r#   zdata:builditr$   N)r‚   rB   r�   rŽ   r�   r   r   r   Ú test_containsTypeMachineFeatures  s    z+SpotChecks.test_containsTypeMachineFeaturesN)r%   r&   r'   rV   r�   r‘   r   r   r   r   r�   
  s   r�   c                   @  s    e Zd ZdZdd„ Zdd„ ZdS )ÚRecordsDigraphActionsz/
    Records calls made to L{FakeDigraph}.
    c                 C  s   |   ¡  d S r6   )Úresetr   r   r   r   Ú__init__/  s    zRecordsDigraphActions.__init__c                 C  s   g | _ g | _d S r6   )ÚrenderCallsÚ	saveCallsr   r   r   r   r“   2  s    zRecordsDigraphActions.resetN)r%   r&   r'   rV   r”   r“   r   r   r   r   r’   *  s   r’   c                   @  s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	ÚFakeDigraphzZ
    A fake L{graphviz.Digraph}.  Instantiate it with a
    L{RecordsDigraphActions}.
    c                 C  s
   || _ d S r6   )Ú	_recorder)r    Zrecorderr   r   r   r”   =  s    zFakeDigraph.__init__c                 K  s   | j j |¡ d S r6   )r˜   r•   Úappend©r    Úkwargsr   r   r   Úrender@  s    zFakeDigraph.renderc                 K  s   | j j |¡ d S r6   )r˜   r–   r™   rš   r   r   r   ÚsaveC  s    zFakeDigraph.saveN)r%   r&   r'   rV   r”   rœ   r�   r   r   r   r   r—   7  s   r—   c                   @  s    e Zd ZdZdd„ Zdd„ ZdS )ÚFakeMethodicalMachinezL
    A fake L{MethodicalMachine}.  Instantiate it with a L{FakeDigraph}
    c                 C  s
   || _ d S r6   ©Z_digraph)r    rˆ   r   r   r   r”   L  s    zFakeMethodicalMachine.__init__c                 C  s   | j S r6   rŸ   r   r   r   r   r�   O  s    zFakeMethodicalMachine.asDigraphN)r%   r&   r'   rV   r”   r�   r   r   r   r   rž   G  s   rž   c                   @  s^   e Z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d„ ZdS )ÚVisualizeToolTestsc                 C  s2   t ƒ | _t| jƒ| _d| _dg| _g | _d| _d S )Nz	tool-testZignoredz	fake.fqpn)r’   ÚdigraphRecorderr—   ÚfakeDigraphÚfakePrognameÚfakeSysPathÚcollectedOutputÚfakeFQPNr   r   r   r   rF   W  s    zVisualizeToolTests.setUpc                 G  s   | j  d |¡¡ d S )Nú )r¥   r™   r‚   )r    Úargsr   r   r   ÚcollectPrints`  s    z VisualizeToolTests.collectPrintsc                 c  s   |t | jƒfV  d S r6   )rž   r¢   )r    Zfqpnr   r   r   ÚfakeFindMachinesc  s    z#VisualizeToolTests.fakeFindMachinesNc                 C  s>   ddl m} ||p| j|p | jg|p(| j|p0| j|p8| jd�S )Nr	   )Útool)Z	_prognameZ_argvZ_syspathZ_findMachinesZ_print)rE   r«   r£   r¦   r¤   rª   r©   )r    ZprognameÚargvZsyspathZfindMachinesÚprintr«   r   r   r   r«   f  s    
ûzVisualizeToolTests.toolc                 C  s&   | j | jgd� |  | jd d¡ dS )z‰
        L{tool} adds '' to sys.path to ensure
        L{automat._discover.findMachines} searches the current
        directory.
        ©r¬   r   r   N)r«   r¦   rP   r¤   r   r   r   r   Útest_checksCurrentDirectorys  s    z.VisualizeToolTests.test_checksCurrentDirectoryc                 C  s@   | j | jdgd� |  | j¡ | j | jdgd� |  | j¡ dS )z6
        Passing -q/--quiet hides all output.
        z--quietr®   z-qN)r«   r¦   ÚassertFalser¥   r   r   r   r   Útest_quietHidesOutput|  s    z(VisualizeToolTests.test_quietHidesOutputc                 C  s�   dD ]†}| j  ¡  g | _| j| j|dgd� |  tdd„ | jD ƒƒ¡ |  t| j j	ƒd¡ | j j	\}|  d 
| j¡|d ¡ |  | j j¡ qd	S )
ze
        Passing an empty string for --image-directory/-i disables
        rendering images.
        )ú--image-directoryz-ir   r®   c                 s  s   | ]}d |kV  qdS ©ÚimageNr   ©r^   Úliner   r   r   Ú	<genexpr>�  s     z6VisualizeToolTests.test_onlySaveDot.<locals>.<genexpr>r   ú{}.dotÚfilenameN)r¡   r“   r¥   r«   r¦   r°   ÚanyrP   rt   r–   Úformatr•   ©r    Úargr   r   r   r   Útest_onlySaveDot…  s    

z#VisualizeToolTests.test_onlySaveDotc                 C  sž   dD ]”}| j  ¡  g | _| j| j|dgd� |  tdd„ | jD ƒƒ¡ |  t| j j	ƒd¡ | j j	\}|  d 
| j¡|d ¡ |  |d	 ¡ |  | j j¡ qd
S )zc
        Passing an empty string for --dot-directory/-d disables saving dot
        files.
        )ú--dot-directoryz-dr   r®   c                 s  s   | ]}d |kV  qdS ©r   Nr   rµ   r   r   r   r·   ¡  s     z8VisualizeToolTests.test_saveOnlyImage.<locals>.<genexpr>r   r¸   r¹   ÚcleanupN)r¡   r“   r¥   r«   r¦   r°   rº   rP   rt   r•   r»   Ú
assertTruer–   r¼   r   r   r   Útest_saveOnlyImage—  s    

z%VisualizeToolTests.test_saveOnlyImagec                 C  sÂ   d}d}| j | jd|d|gd� |  tdd„ | jD ƒƒ¡ |  tdd„ | jD ƒƒ¡ |  t| jjƒd	¡ | jj\}|  |d
 |¡ |  |d ¡ |  t| jj	ƒd	¡ | jj	\}|  |d
 |¡ dS )z’
        Passing different directories to --image-directory and --dot-directory
        writes images and dot files to those directories.
        r´   r   r²   r¿   r®   c                 s  s   | ]}d |kV  qdS r³   r   rµ   r   r   r   r·   »  s     zQVisualizeToolTests.test_saveDotAndImagesInDifferentDirectories.<locals>.<genexpr>c                 s  s   | ]}d |kV  qdS rÀ   r   rµ   r   r   r   r·   ¼  s     r   Ú	directoryrÁ   N)
r«   r¦   rÂ   rº   r¥   rP   rt   r¡   r•   r–   )r    ZimageDirectoryZdotDirectoryÚ
renderCallZsaveCallr   r   r   Ú+test_saveDotAndImagesInDifferentDirectoriesª  s&    ûÿ


z>VisualizeToolTests.test_saveDotAndImagesInDifferentDirectoriesc                 C  sˆ   d}| j | jd|d|gd� |  tdd„ | jD ƒƒ¡ |  t| jjƒd¡ | jj\}|  |d |¡ |  	|d	 ¡ |  	t| jj
ƒ¡ d
S )z�
        Passing the same directory to --image-directory and --dot-directory
        writes images and dot files to that one directory.
        ZimagesAndDotr²   r¿   r®   c                 s  s   | ]}d |kV  qdS )zimage and dotNr   rµ   r   r   r   r·   ×  s     zJVisualizeToolTests.test_saveDotAndImagesInSameDirectory.<locals>.<genexpr>r   rÄ   rÁ   N)r«   r¦   rÂ   rº   r¥   rP   rt   r¡   r•   r°   r–   )r    rÄ   rÅ   r   r   r   Ú$test_saveDotAndImagesInSameDirectoryÇ  s    ûÿ

z7VisualizeToolTests.test_saveDotAndImagesInSameDirectory)NNNNN)r%   r&   r'   rF   r©   rª   r«   r¯   r±   r¾   rÃ   rÆ   rÇ   r   r   r   r   r    S  s   	         ÿ
		r    )'Ú
__future__r   rn   r   r   Zdataclassesr   Útypingr   Zunittestr   r   Zautomatr   r   Z_methodicalr
   Z_typedr   Ztest_discoverr   r   r   r1   r2   r8   rB   rC   r/   rW   r]   rd   rh   r~   r�   r’   r—   rž   r    r   r   r   r   Ú<module>   sP   $L