B
    Wc~                 @   sl  d Z ddlZddlZddl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 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 ddl	mZ ddl	m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! 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, ddl*m-Z- ddl*m.Z. dd l/m0Z0 dd!l/m1Z1 dd"l2m3Z3 dd#l2m4Z4 erdd$l5m6Z6 e%dd%d&d'Z7e8e8d(d)d*Z9ee
ed+geee:e f  f ee:e f d,d-d.Z;eee:e f d/d0d1Z<ed+eee:e f  d2d3d4Z=d+dd5d6d7Z>d+e?d5d8d9Z@ee?d(d:d;ZAeeee? d<d=d>ZBeejC edd?d@dAZDG dBdC dCZEG dDdE dEeFZGG dFdG dGeHZIejJdHdHdIG dJdK dKeee8f ZKeG dLd+ d+ejLZMe8e8dMdNdOZNdPdQee8e?eeee8 f dRdSdTZOdS )UzHCore implementation of the testing process: init, session, runtest loop.    N)Path)Callable)Dict)	FrozenSet)Iterator)List)Optional)Sequence)Set)Tuple)Type)TYPE_CHECKING)Union)nodes)final)overload)Config)directory_arg)ExitCode)hookimpl)PytestPluginManager)
UsageError)Parser)FixtureManager)exit)absolutepath)bestrelpath)
fnmatch_ex)visit)CollectReport)
TestReport)collect_one_node)
SetupState)Literal)parserreturnc             C   s
  | j ddddddddd	d
ddg	d | j dddg d | dd}|jddddddd | d}|jddddd | j dd d!d" |jd#d$d%tdd&d'd( |jd)d*d+d |jd,d*d-d |jd.d*d/d |jd0d1td2d3d4 |jd5d*d6d7d8d9 |jd:d%d;d<d= | d>d?}|jd@dAdBd*dCd |jdDd*dEd |jdFddGdHdI |jdJddGdKdI |jdLddMdNdI |jdOdPd dQtjtdOdRdSdT |jdUd*dVd6dWdX |jdYdZd*d[d6d\dX |jd]d*d^d6d_dX |jd`dadaddbgdcddde | dfdg}|jdhdid t	dQdjdk d S )lNnorecursedirsz)Directory patterns to avoid for recursionargsz*.eggz.*Z_darcsZbuildZCVSZdistZnode_modulesvenvz{arch})typedefaultZ	testpathszZDirectories to search for tests when no files or directories are given on the command lineZgeneralzRunning and selection optionsz-xz--exitfirstZstore_constmaxfail   z,Exit instantly on first error or failed test)actiondestZconsthelpzpytest-warningsz-Wz--pythonwarningsappendz<Set which warnings to report, see -W option of Python itself)r-   r/   filterwarningsZlinelistz_Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings.)r)   r/   z	--maxfailZnumZstorer   z'Exit after first num failures or errors)metavarr-   r)   r.   r*   r/   z--strict-config
store_truezbAny warnings encountered while parsing the `pytest` section of the configuration file raise errorsz--strict-markerszVMarkers not registered in the `markers` section of the configuration file raise errorsz--strictz&(Deprecated) alias to --strict-markersz-cfileZinifilenamezbLoad configuration from `file` instead of trying to locate one of the implicit configuration files)r2   r)   r.   r/   z--continue-on-collection-errorsFcontinue_on_collection_errorsz4Force test execution even if collection errors occur)r-   r*   r.   r/   z	--rootdirZrootdirzDefine root directory for tests. Can be relative path: 'root_dir', './root_dir', 'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: '$HOME/root_dir'.)r-   r.   r/   collect
collectionz--collectonlyz--collect-onlyz--coz&Only collect tests, don't execute themz--pyargsz1Try to interpret all arguments as Python packagesz--ignorepathz-Ignore path during collection (multi-allowed))r-   r2   r/   z--ignore-globz5Ignore path pattern during collection (multi-allowed)z
--deselectZnodeid_prefixzDDeselect item (via node id prefix) during collection (multi-allowed)z--confcutdirZ
confcutdirdir)Zoptnamez1Only load conftest.py's relative to specified dir)r.   r*   r2   r)   r/   z--noconftestZ
noconftestz Don't load any conftest.py files)r-   r.   r*   r/   z--keepduplicatesz--keep-duplicateskeepduplicateszKeep duplicate testsz--collect-in-virtualenvcollect_in_virtualenvz2Don't ignore tests in a local virtualenv directoryz--import-modeZprepend	importlib
importmodez\Prepend/append to sys.path when importing test modules and conftest files. Default: prepend.)r*   choicesr.   r/   Zdebugconfigz(test session debugging and configurationz
--basetempZbasetempz^Base temporary directory for this test run. (Warning: this directory is removed if it exists.))r.   r*   r)   r2   r/   )
ZaddiniZgetgroupZ
_addoptionZ	addoptionintstr	functoolspartialr   validate_basetemp)r$   group rE   +lib/python3.7/site-packages/_pytest/main.pypytest_addoption3   s   

rG   )r8   r%   c             C   sl   d}| st |tttddd}|t t|  rDt ||t  t|  rht || S )NzWbasetemp must not be empty, the current working directory or any parent directory of it)basequeryr%   c             S   s   | |krdS || j kS )z,Return whether query is an ancestor of base.T)parents)rH   rI   rE   rE   rF   is_ancestor   s    z&validate_basetemp.<locals>.is_ancestor)argparseZArgumentTypeErrorr   boolcwdZabsoluteZresolve)r8   msgrK   rE   rE   rF   rC      s    


rC   Session)configdoitr%   c             C   s`  t | }tj|_d}zy4|   d}| jj|d d}|| |pFd|_W nr tk
rn   tj	|_ Y nT t
k
r   tj|_Y n8 ttjfk
r   tjj }tj}t|jtjr|jjdk	r|jj}|dk rtj|j d|jj d | jj|d ||_Y n tk
r   tj|_tjj }y| || j  W nX tjk
r } z6|jdk	rr|j|_tjt!|j" d| d W dd}~X Y nX t|jt#rtjd	 Y nX W dd}t$%|j& |dkrPy| jj'||jd
 W nX tjk
rN } z6|jdk	r |j|_tjt!|j" d| d W dd}~X Y nX | (  X |jS )zSkeleton command line program.r   r,   )session   Nz: 
)excinfoz(mainloop: caught unexpected SystemExit!
)rS   
exitstatus))rP   from_configr   ZOKrW   Z_do_configurehookZpytest_sessionstartr   ZUSAGE_ERRORFailedTESTS_FAILEDKeyboardInterruptr   	Exception_pytest_codeZExceptionInfoZfrom_currentZINTERRUPTED
isinstancevalue
returncodesysstderrwritetypenamerO   Zpytest_keyboard_interruptBaseExceptionZINTERNAL_ERRORZnotify_exceptionoptionr)   __name__
SystemExitoschdir	startpathZpytest_sessionfinishZ_ensure_unconfigure)rQ   rR   rS   Z	initstaterV   rW   excrE   rE   rF   wrap_session  s`    

0
0
ro   )rQ   r%   c             C   s
   t | tS )N)ro   _main)rQ   rE   rE   rF   pytest_cmdline_main<  s    rq   )rQ   rS   r%   c             C   s<   | j j|d | j j|d |jr(tjS |jdkr8tjS dS )z[Default command line protocol for initialization, session,
    running tests and reporting.)rS   r   N)rY   pytest_collectionpytest_runtestlooptestsfailedr   r[   testscollectedZNO_TESTS_COLLECTED)rQ   rS   rE   rE   rF   rp   @  s    
rp   )rS   r%   c             C   s   |    d S )N)perform_collect)rS   rE   rE   rF   rr   M  s    rr   c             C   s   | j r2| jjjs2| d| j | j dkr(dndf | jjjr@dS xpt| jD ]b\}}|d t| jk rt| j|d  nd }|jj	j
||d | jr| | j| jrL| | jqLW dS )Nz%d error%s during collectionr,   s T)itemnextitem)rt   rQ   rh   r5   InterruptedZcollectonly	enumerateitemslenrY   Zpytest_runtest_protocol
shouldfailrZ   
shouldstop)rS   iry   rz   rE   rE   rF   rs   Q  s    
$rs   c                s^   |  tjdrdnd}y| s(dS W n tk
r>   dS X d t fdd| D S )zAttempt to detect if ``path`` is the root of a Virtual Environment by
    checking for the existence of the appropriate activate script.winZScriptsbinF)Zactivatezactivate.cshzactivate.fishZActivatezActivate.batzActivate.ps1c             3   s   | ]}|j  kV  qd S )N)name).0fname)	activatesrE   rF   	<genexpr>v  s    z_in_venv.<locals>.<genexpr>)Zjoinpathrc   platform
startswithis_dirOSErroranyZiterdir)r8   ZbindirrE   )r   rF   _in_venve  s    r   )collection_pathrQ   r%   c                s   |j d j|jd}|pg }|d}|r>|dd |D   |krJdS |j d j|jd}|pdg }|d}|r|d	d |D  t fd
d|D rdS |d}|st rdS d S )NZcollect_ignore)r8   rootpathignorec             s   s   | ]}t |V  qd S )N)r   )r   xrE   rE   rF   r     s    z(pytest_ignore_collect.<locals>.<genexpr>TZcollect_ignore_globZignore_globc             s   s   | ]}t |V  qd S )N)r   )r   r   rE   rE   rF   r     s    c             3   s"   | ]}t  t t|V  qd S )N)fnmatchr@   )r   Zglob)r   rE   rF   r     s    r;   )Z_getconftest_pathlistparentr   	getoptionextendr   r   )r   rQ   Zignore_pathsZ
excludeoptZignore_globsZexcludegloboptZallow_in_venvrE   )r   rF   pytest_ignore_collecty  s(    


r   )r}   rQ   r%   c             C   st   t |dpg }|sd S g }g }x.| D ]&}|j|rD|| q(|| q(W |rp|jj|d || d d < d S )NZdeselect)r}   )tupler   nodeidr   r0   rY   Zpytest_deselected)r}   rQ   Zdeselect_prefixesZ	remainingZ
deselectedZcolitemrE   rE   rF   pytest_collection_modifyitems  s    
r   c               @   s*   e Zd ZeddddZedddZdS )FSHookProxyN)pmr%   c             C   s   || _ || _d S )N)r   remove_mods)selfr   r   rE   rE   rF   __init__  s    zFSHookProxy.__init__)r   c             C   s    | j j|| jd}|| j|< |S )N)Zremove_plugins)r   Zsubset_hook_callerr   __dict__)r   r   r   rE   rE   rF   __getattr__  s    
zFSHookProxy.__getattr__)ri   
__module____qualname__r   r   r@   r   rE   rE   rE   rF   r     s   r   c               @   s   e Zd ZdZdZdS )r{   z*Signals that the test run was interrupted.builtinsN)ri   r   r   __doc__rE   rE   rE   rF   r{     s   r{   c               @   s   e Zd ZdZdS )rZ   z"Signals a stop as failed test run.N)ri   r   r   r   rE   rE   rE   rF   rZ     s   rZ   T)slotsZauto_attribsc               @   s&   e Zd ZU eed< eedddZdS )_bestrelpath_cacher8   )r8   r%   c             C   s   t | j|}|| |< |S )N)r   r8   )r   r8   rrE   rE   rF   __missing__  s    z_bestrelpath_cache.__missing__N)ri   r   r   r   __annotations__r@   r   rE   rE   rE   rF   r     s   
r   c                   s  e Zd ZU eZeZeed< eed< ee	e
f ed< edd fddZeed ddd	Zed
ddZeed
ddZeedddZedddd
ddZeddeeef ddddZeZeedf edddZddddZd ed!d"d#Zd3eeee j! d$d%d&Z"e#d4e$ee  d(ee j% d)d*d+Z&e#d5e$ee  eeee j%e j!f  d)d,d+Z&d6e$ee  eeee j%e j!f  d)d-d+Z&e'ee j%e j!f  d
d.d/Z(ee j%e j!f e'e j% d0d1d2Z)  Z*S )7rP   Z_setupstateZ_fixturemanagerrW   N)rQ   r%   c                sl   t  j|jd d || dd d| _d| _d| _d| _|jj	d| _t
 | _t|j| _| jjj| dd d S )Nrx   )r8   fspathr   rQ   rS   r   r   Fr7   rS   )r   )superr   r   rt   ru   r   r   tracerootget	frozenset_initialpathsr   _bestrelpathcacherQ   pluginmanagerregister)r   rQ   )	__class__rE   rF   r     s    zSession.__init__c             C   s   | j |d}|S )N)rQ   )Z_create)clsrQ   rS   rE   rE   rF   rX     s    zSession.from_config)r%   c             C   s$   d| j j| jt| dd| j| jf S )Nz6<%s %s exitstatus=%r testsfailed=%d testscollected=%d>rW   z<UNSET>)r   ri   r   getattrrt   ru   )r   rE   rE   rF   __repr__  s    
zSession.__repr__c             C   s
   | j jjS )zQThe path from which pytest was invoked.

        .. versionadded:: 7.0.0
        )rQ   invocation_paramsr9   )r   rE   rE   rF   rm     s    zSession.startpath)	node_pathr%   c             C   s
   | j | S )N)r   )r   r   rE   rE   rF   _node_location_to_relpath  s    z!Session._node_location_to_relpathT)Ztryfirstc             C   s(   | j r| | j | jr$| | jd S )N)r   rZ   r   r{   )r   rE   rE   rF   pytest_collectstart  s    zSession.pytest_collectstart)reportr%   c             C   sH   |j rDt|dsD|  jd7  _| jd}|rD| j|krDd| j | _d S )NZwasxfailr,   r+   zstopping after %d failures)Zfailedhasattrrt   rQ   getvaluer   )r   r   r+   rE   rE   rF   pytest_runtest_logreport  s
    z Session.pytest_runtest_logreportzos.PathLike[str])r8   r%   c             C   s    t |tr|nt|}|| jkS )N)r`   r   r   )r   r8   Zpath_rE   rE   rF   
isinitpath  s    zSession.isinitpath)r   c             C   sr   t |tr|nt|}| jj}|j|| jd| jjd}|j|}|rfddl	m
} |t||}n| jj}|S )Nr=   )r   r,   )PathAwareHookProxy)r`   r   rQ   r   Z_getconftestmodulesr   r   Z_conftest_plugins
differenceZconfig.compatr   r   rY   )r   r   r8   r   Zmy_conftestmodulesr   r   proxyrE   rE   rF   gethookproxy  s    
zSession.gethookproxyzos.DirEntry[str])direntryr%   c                sb   |j dkrdS t|j |  j}|j | jdr8dS | jd}t fdd|D r^dS dS )N__pycache__F)r   rQ   r&   c             3   s   | ]}t | V  qd S )N)r   )r   pat)r   rE   rF   r   5  s    z#Session._recurse.<locals>.<genexpr>T)	r   r   r8   r   r   r   rQ   Zgetinir   )r   r   ihookZnorecursepatternsrE   )r   rF   _recurse-  s    

zSession._recurse)r   handle_dupesr%   c             C   s   |  s(td|| | | | |}| |sP|j|| j	drPdS |r| j	
d}|s| j	jj}||krzdS || |j|| dS )Nz9{!r} is not a file (isdir={!r}, exists={!r}, islink={!r}))r   rQ   rE   r:   )Z	file_pathr   )is_fileAssertionErrorformatr   exists
is_symlinkr   r   r   rQ   r   r   Z_duplicatepathsaddZpytest_collect_file)r   r   r   r   r:   Zduplicate_pathsrE   rE   rF   _collectfile9  s    




zSession._collectfile.zLiteral[True])r'   genitemsr%   c             C   s   d S )NrE   )r   r'   r   rE   rE   rF   rv   Q  s    zSession.perform_collectc             C   s   d S )NrE   )r   r'   r   rE   rE   rF   rv   W  s    c          
   C   s  |dkr| j j}| d| | | jj jd7  _g | _g | _g | _| j j}| j}z6g }xD|D ]<}t	| j j
j|| j jjd\}}| j||f || q^W t|| _t| }	| jj|	d | jj jd8  _| jr.g }
xH| jD ]>\}}|r|
d| d|d|d	 q|
d
|  qW t|
 |s<|	j}n,|	jrhx"|	jD ]}| j| | qLW | j j  |j| | j |d W d|j| d X t|| _|S )a  Perform the collection phase for this session.

        This is called by the default :hook:`pytest_collection` hook
        implementation; see the documentation of this hook for more details.
        For testing purposes, it may also be called directly on a fresh
        ``Session``.

        This function normally recursively expands any collectors collected
        from the session to their items, and only items are returned. For
        testing purposes, this may be suppressed by passing ``genitems=False``,
        in which case the return value contains these collectors unexpanded,
        and ``session.items`` is empty.
        Nrv   r,   )	as_pypath)r   znot found: z

(no name z in any of )zfound no collectors for )rS   rQ   r}   )rS   )rQ   r'   r   r   indent	_notfound_initial_partsr}   rY   resolve_collection_argumentr   r9   rh   Zpyargsr0   r   r   r!   r   pytest_collectreportr   resultpassedr   r   r   Zcheck_pendingr   Zpytest_collection_finishr~   ru   )r   r'   r   rY   r}   Zinitialpathsargr   partsreperrorsZ
collectorsnoderE   rE   rF   rv   ]  sR    


c          	   c   sL  ddl m} i }i }i }i }x(| jD ]\}}| d||f | jj jd7  _| jdds| jj}x|f|j	D ]t}	|
|sP |	 rv|	d }
|
 rv|
|krv| j|
dd}|rvt|d |r|d |t|	< |d g||d j< qvW | r|rtd	||ft }xtt|| jD ]}| s:q(t|j}|j}||kr|| |d }
|
 rx2| |
D ]$}|V  t||r|||t|< q|W t||krq(xF| |D ]8}t||jf}||kr|| V  n|||< |V  qW q(W n*| st||kr*|| }n.|t|j| }|j|dd}|rX|||< g }||fg}xB|r| d
|| | jj jd7  _| \}}x|D ]}|s|| qt|tjs̐qt||jf}||kr|| }nt |}|||< |j!rng }xD|j"D ]:}|j#|d ks@|j#$dd |d kr|| qW |r||||dd  f n|j%j&|d qW | dt'|d | jj jd8  _qjW |sd(t|f|}| j)||f q&|j#dkr(t|d |r(yt*t+|d , V  W q& t-k
r$   Y q&X q&|E d H  | jj jd8  _q&W d S )Nr   )Packagezprocessing argumentr,   ZdoctestmodulesFz__init__.py)r   zinvalid arg 
matchnodes[)r   zmatchnodes finished -> r   z::).Z_pytest.pythonr   r   r   r   r   rQ   r   r   rJ   Z_is_in_confcutdirr   r   r   r`   r@   r8   r   setr   r   r   r   r   r   r)   r   popr0   r   	Collectorr   r!   r   r   r   splitr   r   r~   joinr   nextiterr6   StopIteration)r   r   Znode_cache1Znode_cache2Zmatchnodes_cacheZ	pkg_rootsZargpathnamesr   r   ZpkginitcolZ	seen_dirsr   r8   dirpathr   Zkey2Zcollect_rootZmatchingZworkr   Z
matchnamesr   keyr   Zsubmatchnodesr   Z
report_argrE   rE   rF   r6     s    
















zSession.collect)r   r%   c             c   s~   |  d| t|tjr.|jj|d |V  nLt|tjs>tt|}|j	rlx|j
D ]}| |E d H  qTW |jj|d d S )Nr   )ry   )r   )r   r`   r   Itemr   Zpytest_itemcollectedr   r   r!   r   r   r   r   )r   r   r   ZsubnoderE   rE   rF   r   6  s    zSession.genitems)T)..)..)NT)+ri   r   r   r{   rZ   r"   r   r   r   r?   r   r   r   classmethodrX   r@   r   propertyr   rm   r   r   r   r    r   r   r   rM   r   r   r   r	   r   r   r   r   r   r   rv   r   r6   r   __classcell__rE   rE   )r   rF   rP     sF   
	
 E )module_namer%   c          
   C   sj   yt j| }W n tttfk
r*   | S X |dksH|jdksH|jdkrL| S |jr`tj	
|jS |jS dS )zTSearch sys.path for the given a dotted module name, and return its file system path.N	namespace)r<   util	find_specAttributeErrorImportError
ValueErrororiginsubmodule_search_locationsrk   r8   dirname)r   specrE   rE   rF   search_pypathF  s    r   F)r   )invocation_pathr   r   r%   c      
      C   s   t |d\}}}|d^}}|r>|d  | | |d< |rJt|}| | }t|}| s~|rjdnd}	t|	j|d|r| r|rdnd}	t|	j|d||fS )	a`  Parse path arguments optionally containing selection parts and return (fspath, names).

    Command-line arguments can point to files and/or directories, and optionally contain
    parts for specific tests selection, for example:

        "pkg/tests/test_foo.py::TestClass::test_foo"

    This function ensures the path exists, and returns a tuple:

        (Path("/full/path/to/pkg/tests/test_foo.py"), ["TestClass", "test_foo"])

    When as_pypath is True, expects that the command-line argument actually contains
    module paths instead of file-system paths:

        "pkg.tests.test_foo::TestClass::test_foo"

    In which case we search sys.path for a matching module, and then return the *path* to the
    found module.

    If the path doesn't exist, raise UsageError.
    If the path is a directory and selection parts are present, raise UsageError.
    r   z::z9module or package not found: {arg} (missing __init__.py?)z"file or directory not found: {arg})r   z9package argument cannot contain :: selection parts: {arg}z;directory argument cannot contain :: selection parts: {arg})	r@   	partitionr   r   r   r   r   r   r   )
r  r   r   rH   ZsquacketrestZstrpathr   r   rO   rE   rE   rF   r   W  s"    r   )Pr   rL   r   rA   r<   rk   rc   Zpathlibr   typingr   r   r   r   r   r   r	   r
   r   r   r   r   attrZ_pytest._coder^   r   Z_pytest.compatr   r   Z_pytest.configr   r   r   r   r   r   Z_pytest.config.argparsingr   Z_pytest.fixturesr   Z_pytest.outcomesr   Z_pytest.pathlibr   r   r   r   Z_pytest.reportsr   r    Z_pytest.runnerr!   r"   Ztyping_extensionsr#   rG   r@   rC   r?   ro   rq   rp   rr   rM   rs   r   r   r   r   r   r\   r{   r]   rZ   rw   r   ZFSCollectorrP   r   r   rE   rE   rE   rF   <module>   s    69	
   