B
    '(b4                 @   s  d Z ddlZddl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 ddlmZ ddlmZ dd	lmZmZmZ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& ddl'm(Z( ddl)Z)dZ*G dd deZ+ee, ee, dddZ-dS )a  Test cases for fine-grained incremental checking.

Each test cases runs a batch build followed by one or more fine-grained
incremental steps. We verify that each step produces the expected output.

See the comment at the top of test-data/unit/fine-grained.test for more
information.

N.B.: Unlike most of the other test suites, testfinegrained does not
rely on an alt_lib_path for finding source files. This means that they
can test interactions with the lib_path that is built implicitly based
on specified sources.
    N)ListDictAnyTupleUnioncast)build)BuildSource)CompileError)Options)test_temp_dir)DataDrivenTestCase	DataSuite
UpdateFile
DeleteFile)assert_string_arrays_equalparse_optionsassert_module_equivalenceassert_target_equivalenceperform_file_operations)check_consistency)DEFAULT_STATUS_FILE)Server)parse_config_file)create_source_listFc               @   sD  e Zd ZdddddddgZdZeed	d
dZedd	ddZe	eee
dddZeee ee	 dddZe
ee ee	 dddZeee	  ee	 dddZe	edddZeeeef  ee
e
ee	eeeee	 eee	  f d	dd Ze	ee
ee d!d"d#Zeee	e	ee	 d$d%d&Ze	eeee	e	f  d'd(d)ZdS )*FineGrainedSuitezfine-grained.testzfine-grained-cycles.testzfine-grained-blockers.testzfine-grained-modules.testz fine-grained-follow-imports.testzfine-grained-suggest.testzfine-grained-attr.testF)testcasereturnc             C   s@   | j r.|jdkrdS |jr<|jd dkr<dS n|jdkr<dS dS )Nz-only_when_nocacheTr   z==z-only_when_cacheF)	use_cacheZ	only_whenoutput)selfr    r!   H/home/dcms/DCMS/lib/python3.7/site-packages/mypy/test/testfinegrained.pyshould_skip;   s    

zFineGrainedSuite.should_skipNc             C   s  |  |rt  d S d|j}tjtd}t|ddd}|	| W d Q R X | j
||dd}| j
||dd}t|t}| |}d	}	| ||	|}
|	|kr| ||
}n| ||
}g }|r|t| |jst|| |	|||jj |jrtrt|j | }g }xP|D ]H}|	d	7 }	| |||||||	|\}}|d
 || || q W dd |D }t|j|d|j d|j  d |j!rt|j!| "|d|j d|j  d d S )N
mainwutf8)encodingF)build_cacheT   z==c             S   s   g | ]}| d dqS )\/)replace).0liner!   r!   r"   
<listcomp>   s    z-FineGrainedSuite.run_case.<locals>.<listcomp>zInvalid output (z, line )zInvalid active triggers ()#r#   pytestskipjoininputospathr   openwriteget_optionsr   r   get_build_stepsparse_sourcesr   	run_checkextendnormalize_messagestmpdirAssertionErrormaybe_suggestnamefine_grained_managerCHECK_CONSISTENCYr   Z
find_stepsperform_stepappendr   r   filer/   	triggeredformat_triggered)r    r   main_srcZ	main_pathfoptionsbuild_optionsservernum_regular_incremental_stepsstepsourcesmessagesaZstepsZall_triggered
operationsr   rI   r!   r!   r"   run_caseL   sb    








zFineGrainedSuite.run_case)sourcer   r)   r   c             C   s   t ||dd}d|_d|_d|_d|_| |_| jo8| |_| j|_d|_	t
d|d kr`d|_x4|jD ]*\}}d|ksd|krht|d	d
 | P qhW |S )Nr*   )incremental_stepTFzflags:.*--follow-importserrorzmypy.inizpyproject.tomlc               S   s   d S )Nr!   r!   r!   r!   r"   <lambda>       z.FineGrainedSuite.get_options.<locals>.<lambda>)r   incrementalZuse_builtins_fixturesshow_tracebackZerror_summaryZfine_grained_incrementalr   Zuse_fine_grained_cacheZcache_fine_grainedZlocal_partial_typesresearchZfollow_importsfilesr   )r    rW   r   r)   rM   rC   _r!   r!   r"   r:      s     zFineGrainedSuite.get_options)rO   rR   r   c             C   s.   |j |ddd}tt|d p"|d }| S )NF)is_ttyZterminal_widthouterr)checkr   str
splitlines)r    rO   rR   responserd   r!   r!   r"   r=      s    zFineGrainedSuite.run_check)rM   rR   r   c          
   C   s>   yt j ||d}W n$ tk
r6 } z|jS d }~X Y nX |jS )N)rR   rM   )r   r
   rS   errors)r    rM   rR   resulter!   r!   r"   r      s    zFineGrainedSuite.build)rI   r   c             C   sT   g }xJt |D ]>\}}dd |D }t|}|d|d d|f   qW |S )Nc             S   s   g | ]}| d s|qS )z__>)endswith)r.   Ztriggerr!   r!   r"   r0      s    z5FineGrainedSuite.format_triggered.<locals>.<listcomp>z%d: %s   z, )	enumeratesortedrG   r4   strip)r    rI   rk   nZtriggersfilteredr!   r!   r"   rJ      s    $z!FineGrainedSuite.format_triggered)program_textr   c             C   s6   | j s
dS tjd|tjd}|dk	r2t|dS dS )zHGet the number of regular incremental steps to run, from the test sourcer   z# num_build_steps: ([0-9]+)$)flagsNr*   )r   r^   r_   	MULTILINEintgroup)r    rt   mr!   r!   r"   r;      s    z FineGrainedSuite.get_build_steps)	rU   rO   rM   rN   r   rK   rQ   rP   r   c	             C   sL  t | | |||}	||kr,| ||	}
n| ||	}
g }g }g }g }|jrtr\t|j ||jj |jj	}dd |jj
D }|jj}|j|d }|dk	rtdt|d  || |j|d }|dk	rtdt|d  || |j|}|rtdt| || t|
}
|
}|js*t|| ||||jj ||fS )zPerform one fine-grained incremental build step (after some file updates/deletions).

        Return (mypy output, triggered targets).
        c             S   s   g | ]\}}|qS r!   r!   )r.   modrH   r!   r!   r"   r0      s    z1FineGrainedSuite.perform_step.<locals>.<listcomp>r*   NstaleZ	recheckedtargets)r   r<   r   r=   rD   rE   r   rG   rI   Zupdated_modulesZchanged_modulesZprocessed_targetsZexpected_stale_modulesgetr   rg   Zexpected_rechecked_modulesZexpected_fine_grained_targetsr   r?   r@   rA   r>   rB   rC   )r    rU   rO   rM   rN   r   rK   rQ   rP   rR   Znew_messagesupdatedchangedr|   rI   Zexpected_staleZexpected_recheckedexpectedrT   r!   r!   r"   rF      sH    

zFineGrainedSuite.perform_step)rt   rX   rM   r   c       	      C   s   t jd|t jd}d| d}t j||t jd}|dk	r<|}|rfdd |d  D }t||S ttj	
td	d
d}|gttg|dd S dS )a!  Return target BuildSources for a test case.

        Normally, the unit tests will check all files included in the test
        case. This differs from how testcheck works by default, as dmypy
        doesn't currently support following imports.

        You can override this behavior and instruct the tests to check
        multiple modules by using a comment like this in the test case
        input:

          # cmd: main a.py

        You can also use `# cmdN:` to have a different cmd for incremental
        step N (2, 3, ...).

        z# cmd: mypy ([a-zA-Z0-9_./ ]+)$)ru   z# cmdz: mypy ([a-zA-Z0-9_./ ]+)$Nc             S   s   g | ]}t jt|qS r!   )r6   r7   r4   r   )r.   r7   r!   r!   r"   r0   !  s    z2FineGrainedSuite.parse_sources.<locals>.<listcomp>r*   r%   __main__T)Zallow_empty_dir)r^   r_   rv   rx   rq   splitr   r	   r6   r7   r4   r   )	r    rt   rX   rM   ry   regexZalt_mpathsbaser!   r!   r"   r<     s    
zFineGrainedSuite.parse_sources)rQ   rO   srctmp_dirr   c             C   sH  g }|  ||}x,|D ]"\}}d|k}	d|k}
d|k}d|k}d|k}td|}|rht|dnd }td|}|r|dnd }td	|}|rt|dnd }tttt	f |j
| |	||||||
|d
	}d|kr|d n|d |d  }|	r(|dd}|tj|tjj d}|| d qW t|S )Nz--jsonz--callsitesz--no-anyz--no-errorsz
--try-textz--flex-any=([0-9.]+)r*   z--use-fixme=(\w+)z--max-guesses=([0-9]+))jsonno_any	no_errorstry_textflex_any	use_fixme	callsitesmax_guessesrY   rd   re   z\\r+    r$   )get_suggestr^   matchfloatrx   rw   r   r   rg   r   Zcmd_suggestrq   r-   r6   r7   realpathsepr>   r   r?   )r    rQ   rO   r   r   r   r|   ru   targetr   r   r   r   r   ry   r   r   r   resvalr!   r!   r"   rB   *  s2     zFineGrainedSuite.maybe_suggest)rt   rX   r   c             C   s6   |dkrdnt |}d| d}tj||tjd}|S )Nr*   z1?z	# suggestz3: (--[a-zA-Z0-9_\-./=?^ ]+ )*([a-zA-Z0-9_.:/?^ ]+)$)ru   )rg   r^   findallrv   )r    rt   rX   Zstep_bitr   ry   r!   r!   r"   r   F  s    zFineGrainedSuite.get_suggest)__name__
__module____qualname__r`   r   r   boolr#   rV   rg   r   r:   r   r   r	   r=   r   rJ   rw   r;   r   r   r   r   rF   r<   rB   r   r!   r!   r!   r"   r   ,   s@   B	
$4%r   )rS   r   c             C   s   dd | D S )Nc             S   s&   g | ]}t d t tj d|qS )z^tmpr   )r^   subescaper6   r   )r.   messager!   r!   r"   r0   O  s   z&normalize_messages.<locals>.<listcomp>r!   )rS   r!   r!   r"   r?   N  s    r?   ).__doc__r6   r^   typingr   r   r   r   r   r   Zmypyr   Zmypy.modulefinderr	   Zmypy.errorsr
   Zmypy.optionsr   Zmypy.test.configr   Zmypy.test.datar   r   r   r   Zmypy.test.helpersr   r   r   r   r   Zmypy.server.mergecheckr   Zmypy.dmypy_utilr   Zmypy.dmypy_serverr   Zmypy.config_parserr   Zmypy.find_sourcesr   r2   rE   r   rg   r?   r!   r!   r!   r"   <module>   s*      $