B
    `                @   sj  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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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l0m1Z1 ddl0m2Z2 ddl0m3Z3 ddl0m4Z4 ddl0m5Z5 dd l0m6Z6 dd!l7m8Z8 dd"l9m:Z: dd#l;m<Z< dd$l;m=Z= dd%l>m?Z? dd&l@mAZA dd'lBmCZC dd(lBmDZD dd)lEmFZF dd*lEmGZG dd+lEmHZH dd,lImJZJ dd-lKmLZL dd.lKmMZM dd/lNmOZO dd0lPmQZQ erdd1lRmSZS ddlTZTd2gZUd3gZVe8dd4d5d6ZWe2dd7d8d9ZXG d:d; d;ZYe<e=d<d=d>d?Z(G d@d< d<ZZee[ ee[ dAdBdCZ\G dDdE dEZ]G dFdG dGZ^e<dHdIdJdKZ_e<dLdMe=edL d=dNdOZ`e<e=eOdPdQdRdSZae<dPdTdUdVdWZbe<edX dIdYdZZce<ee2ddf dId[d\Zdeed]Zfeed^ZgG d_d` d`ZhG dadb dbZiG dcdd ddZjG dedf dfZke/G dgdP dPZlG dhdH dHZme/e#jndidididjG dkdT dTZoG dldL dLZpdS )mzZ(Disabled by default) support for testing pytest and pytest plugins.

PYTEST_DONT_REWRITE
    N)fnmatch)StringIO)Path)Any)Callable)Dict)	Generator)Iterable)List)Optional)overload)Sequence)TextIO)Tuple)Type)TYPE_CHECKING)Union)WeakKeyDictionary)	IniConfig)SectionWrapper)timing)Source)_get_multicapture)final)_PluggyPlugin)Config)ExitCode)hookimpl)main)PytestPluginManager)Parser)check_ispytest)fixture)FixtureRequest)Session)MonkeyPatch)	Collector)Item)fail)importorskip)skip)make_numbered_dir)CollectReport)
TestReport)TempPathFactory)PytestWarning)LiteralZpytester_assertionsz/var/lib/sss/mc/passwd)parserreturnc             C   s:   | j dddddd | j ddd	d
dd | jddd d S )Nz--lsof
store_truelsofFz"run FD checks if lsof is available)actiondestdefaulthelpz--runpytest	inprocess	runpytest)r9   
subprocesszYrun pytest sub runs in tests using an 'inprocess' or 'subprocess' (python -m main) method)r7   r6   choicesr8   pytester_example_dirz1directory to take the pytester example files from)r8   )Z	addoptionZaddini)r1    r>   X/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/_pytest/pytester.pypytest_addoptionQ   s    r@   )configr2   c             C   s4   |  dr$t }| r$| j| | dd d S )Nr4   markerszlpytester_example_path(*path_segments): join the given path segments to `pytester_example_dir` for this test.)getvalueLsofFdLeakCheckermatching_platformpluginmanagerregisterZaddinivalue_line)rA   checkerr>   r>   r?   pytest_configurej   s    
rI   c               @   sT   e Zd Zeeeef  dddZedddZe	ddde
ed d	d
dZdS )rD   )r2   c             C   s   t jdddtt ft jt jdddj}ttddd}g }xf|	d	D ]X}||rJ|	d
}|d dd  }|d dd  }|t
krqJ|drJ|||f qJW |S )Nr4   z-Ffn0z-pT)stdoutstderrcheckuniversal_newlines)liner2   c             S   s*   |  do(d| ko(d| ko(d| ko(d| kS )NfZdeletedZmemtxtcwd)
startswith)rN   r>   r>   r?   isopen   s
    
z0LsofFdLeakChecker.get_open_files.<locals>.isopen
 r      /)r;   runstrosgetpidPIPEDEVNULLrJ   boolsplit
IGNORE_PAMrR   append)selfoutrS   Z
open_filesrN   fieldsfdfilenamer>   r>   r?   get_open_filesx   s$    


z LsofFdLeakChecker.get_open_filesc          	   C   s6   yt jddd W n tt jfk
r,   dS X dS d S )N)r4   z-vT)rL   F)r;   rX   OSErrorCalledProcessError)rb   r>   r>   r?   rE      s
    z#LsofFdLeakChecker.matching_platformT)ZhookwrapperZtryfirst)NNN)itemr2   c          	   #   s   |   }d V  ttdr t  |   }dd |D dd |D    fdd|D }|rdt| fdd |D dd
d |D ddd |D dt| d|j df}|td	| d S )Npypy_version_infoc             S   s   h | ]}|d  qS )r   r>   ).0tr>   r>   r?   	<setcomp>   s    z<LsofFdLeakChecker.pytest_runtest_protocol.<locals>.<setcomp>c                s   g | ]}|d   kr|qS )r   r>   )rl   rm   )new_fdsr>   r?   
<listcomp>   s    z=LsofFdLeakChecker.pytest_runtest_protocol.<locals>.<listcomp>z***** %s FD leakage detectedc             s   s   | ]}t |V  qd S )N)rY   )rl   rO   r>   r>   r?   	<genexpr>   s    z<LsofFdLeakChecker.pytest_runtest_protocol.<locals>.<genexpr>*** Before:c             s   s   | ]}t |V  qd S )N)rY   )rl   rO   r>   r>   r?   rq      s    
*** After:c             s   s   | ]}t |V  qd S )N)rY   )rl   rO   r>   r>   r?   rq      s    z*** function %s:%s: %s zSee issue #2366rT   )rr   )rs   )
rg   hasattrsysgccollectlenlocationwarnr/   join)rb   rj   lines1lines2Zleaked_fileserrorr>   )ro   r?   pytest_runtest_protocol   s$    

z)LsofFdLeakChecker.pytest_runtest_protocolN)__name__
__module____qualname__r
   r   rY   rg   r^   rE   r   r'   r   r   r>   r>   r>   r?   rD   w   s   
rD   	PytestArg)requestr2   c             C   s   t | S )zReturn a helper which offers a gethookrecorder(hook) method which
    returns a HookRecorder instance which helps to make assertions about called
    hooks.)r   )r   r>   r>   r?   _pytest   s    r   c               @   s*   e Zd ZeddddZddddZdS )	r   N)r   r2   c             C   s
   || _ d S )N)_request)rb   r   r>   r>   r?   __init__   s    zPytestArg.__init__HookRecorder)r2   c             C   s   t |j}| j|j |S )N)r   Z_pmr   addfinalizerfinish_recording)rb   hookZhookrecorderr>   r>   r?   gethookrecorder   s    
zPytestArg.gethookrecorder)r   r   r   r#   r   r   r>   r>   r>   r?   r      s   )valuesr2   c             C   s   dd | D S )zDOnly return names from iterator values without a leading underscore.c             S   s   g | ]}|d  dkr|qS )r   _r>   )rl   xr>   r>   r?   rp      s    z$get_public_names.<locals>.<listcomp>r>   )r   r>   r>   r?   get_public_names   s    r   c               @   s<   e Zd ZeddddZedddZer8edd	d
ZdS )
ParsedCallN)namer2   c             C   s   | j | || _d S )N)__dict__update_name)rb   r   kwargsr>   r>   r?   r      s    zParsedCall.__init__)r2   c             C   s$   | j  }|d= d| jd|dS )Nr   z<ParsedCall z(**z)>)r   copyr   )rb   dr>   r>   r?   __repr__   s    
zParsedCall.__repr__)keyc             C   s   d S )Nr>   )rb   r   r>   r>   r?   __getattr__   s    zParsedCall.__getattr__)r   r   r   rY   r   r   r   r   r>   r>   r>   r?   r      s   r   c               @   sD  e Zd ZdZeddddZddddZeee	e f e
e d	d
dZeeeef  ddddZeedddZeedddZedee d	ddZedee d	ddZed2eee	e f eeeef  d	ddZd3eee	e f eeeef  d	ddZd4eeee	e f ee eeef ddd Zedee d	d!d"Zedee d	d#d"Zed5eee	e f eeeef  d	d$d"Zd6eee	e f eeeef  d	d%d"Zee dd&d'Zeee eeeef  eeeef  f dd(d)Ze
e dd*d+Zd7eeedd-d.d/Zddd0d1ZdS )8r   zRecord all hooks called in a plugin manager.

    This wraps all the hook calls in the plugin manager, recording each call
    before propagating the normal calls.
    N)rF   r2   c                sH   | _ g  _d  _td d fdd}td ddd}||| _d S )N)	hook_namer2   c                s    j t| | d S )N)callsra   r   )r   
hook_implsr   )rb   r>   r?   before   s    z%HookRecorder.__init__.<locals>.beforec             S   s   d S )Nr>   )outcomer   r   r   r>   r>   r?   after   s    z$HookRecorder.__init__.<locals>.after)Z_pluginmanagerr   retrY   Zadd_hookcall_monitoring_undo_wrapping)rb   rF   r   r   r>   )rb   r?   r      s    zHookRecorder.__init__)r2   c             C   s   |    d S )N)r   )rb   r>   r>   r?   r      s    zHookRecorder.finish_recording)namesr2   c                s&   t  tr    fdd| jD S )Nc                s   g | ]}|j  kr|qS r>   )r   )rl   call)r   r>   r?   rp      s    z)HookRecorder.getcalls.<locals>.<listcomp>)
isinstancerY   r_   r   )rb   r   r>   )r   r?   getcalls   s    
zHookRecorder.getcalls)entriesr2   c       	      C   s   d}d}t |}tdj}x|r|d\}}xt| j|d  D ]p\}}|j|krtd|| t	|||j
rtdt|d| ntdt|d| qD||d 7 }P td	|d
| qDW td|d| qW d S )NTr   rV   Z	NAMEMATCHZCHECKERMATCHz->ZNOCHECKERMATCH-ZNONAMEMATCHwithzcould not find z check )listru   	_getframef_localspop	enumerater   r   printevalr   reprr(   )	rb   r   __tracebackhide__iZ
backlocalsr   rL   indr   r>   r>   r?   assert_contains   s"    
zHookRecorder.assert_contains)r   r2   c             C   sh   d}x,t | jD ]\}}|j|kr| j|= |S qW d|dg}|dd | jD  td| d S )NTzcould not find call z, in:c             S   s   g | ]}d | qS )z  %sr>   )rl   r   r>   r>   r?   rp     s    z(HookRecorder.popcall.<locals>.<listcomp>rT   )r   r   r   extendr(   r{   )rb   r   r   r   r   linesr>   r>   r?   popcall  s    
zHookRecorder.popcallc             C   s*   |  |}t|dks"t||f|d S )NrV   r   )r   rx   AssertionError)rb   r   r   r>   r>   r?   getcall  s    
zHookRecorder.getcallzLiteral['pytest_collectreport']c             C   s   d S )Nr>   )rb   r   r>   r>   r?   
getreports$  s    zHookRecorder.getreportsz#Literal['pytest_runtest_logreport']c             C   s   d S )Nr>   )rb   r   r>   r>   r?   r   *  s    pytest_collectreportpytest_runtest_logreportc             C   s   d S )Nr>   )rb   r   r>   r>   r?   r   0  s    c             C   s   dd |  |D S )Nc             S   s   g | ]
}|j qS r>   )report)rl   r   r>   r>   r?   rp   A  s    z+HookRecorder.getreports.<locals>.<listcomp>)r   )rb   r   r>   r>   r?   r   :  s     r   r   )	inamepartr   whenr2   c             C   s   g }xX| j |dD ]H}|s,|jdkr,|jr,q|r<|j|kr<q|rP||jdkr|| qW |sptd|f t|dkrtd|||d S )z5Return a testreport whose dotted import path matches.)r   r   z::z?could not find test report matching %r: no test reports at all!rV   z-found 2 or more testreports matching {!r}: {}r   )	r   r   passedZnodeidr_   ra   
ValueErrorrx   format)rb   r   r   r   r   repr>   r>   r?   matchreportC  s"    


zHookRecorder.matchreportc             C   s   d S )Nr>   )rb   r   r>   r>   r?   getfailuresc  s    zHookRecorder.getfailuresc             C   s   d S )Nr>   )rb   r   r>   r>   r?   r   i  s    c             C   s   d S )Nr>   )rb   r   r>   r>   r?   r   o  s    c             C   s   dd |  |D S )Nc             S   s   g | ]}|j r|qS r>   )failed)rl   r   r>   r>   r?   rp     s    z,HookRecorder.getfailures.<locals>.<listcomp>)r   )rb   r   r>   r>   r?   r   y  s    c             C   s
   |  dS )Nr   )r   )rb   r>   r>   r?   getfailedcollections  s    z!HookRecorder.getfailedcollectionsc             C   s   g }g }g }xl|  dD ]^}|jrF|jdkrvt|ts:t|| q|jrX|| q|jsltd||| qW |||fS )N)r   r   r   zUnexpected outcome: )	r   r   r   r   r-   r   ra   skippedr   )rb   r   r   r   r   r>   r>   r?   listoutcomes  s    

zHookRecorder.listoutcomesc             C   s   dd |   D S )Nc             S   s   g | ]}t |qS r>   )rx   )rl   r   r>   r>   r?   rp     s    z.HookRecorder.countoutcomes.<locals>.<listcomp>)r   )rb   r>   r>   r?   countoutcomes  s    zHookRecorder.countoutcomesr   )r   r   r   r2   c             C   s,   d}ddl m} |  }|||||d d S )NTr   )assertoutcome)r   r   r   )_pytest.pytester_assertionsr   r   )rb   r   r   r   r   r   outcomesr>   r>   r?   r     s
    zHookRecorder.assertoutcomec             C   s   g | j d d < d S )N)r   )rb   r>   r>   r?   clear  s    zHookRecorder.clear)r   )r   )r   r   N)r   )r   )r   r   r   )r   r   r   __doc__r   r   r   r   rY   r	   r
   r   r   r   r   r   r   r   r   r,   r   r-   r   r   r   r   r   intr   r   r   r>   r>   r>   r?   r      sR    
  	r   LineComp)r2   c               C   s   t  S )zeA :class: `LineComp` instance for checking that an input linearly
    contains a sequence of strings.)r   r>   r>   r>   r?   linecomp  s    r   LineMatcher)r   c             C   s   t S )zA reference to the :class: `LineMatcher`.

    This is instantiable with a list of lines (without their trailing newlines).
    This is useful for testing large texts, such as the output of commands.
    )r   )r   r>   r>   r?   LineMatcher_fixture  s    r   Pytester)r   tmp_path_factoryr2   c             C   s   t | |ddS )a  
    Facilities to write tests/configuration files, execute pytest in isolation, and match
    against expected output, perfect for black-box testing of pytest plugins.

    It attempts to isolate the test run from external factors as much as possible, modifying
    the current working directory to ``path`` and environment variables during initialization.

    It is particularly useful for testing plugins. It is similar to the :fixture:`tmp_path`
    fixture but provides methods which aid in testing pytest itself.
    T)	_ispytest)r   )r   r   r>   r>   r?   pytester  s    r   Testdir)r   r2   c             C   s   t | ddS )z
    Identical to :fixture:`pytester`, and provides an instance whose methods return
    legacy ``py.path.local`` objects instead when applicable.

    New code should avoid using :fixture:`testdir` in favor of :fixture:`pytester`.
    T)r   )r   )r   r>   r>   r?   testdir  s    r   )NNNc              c   s&   t  } t }d V  |  |   d S )N)SysPathsSnapshotSysModulesSnapshotrestore)Z	snappathsZsnapmodsr>   r>   r?   _sys_snapshot  s
    r   c              c   s$   ddl m}  |  }|V  |  d S )Nr   )
get_config)_pytest.configr   _ensure_unconfigure)r   rA   r>   r>   r?   _config_for_test  s    r   z
\d+\.\d\dsz(\d+) (\w+)c            	   @   s   e Zd ZdZeeef ee ee e	ddddZ
edddZeeef dd	d
Zeeeef dddZdeeeeeeddddZdS )	RunResultz The result of running a command.N)r   outlineserrlinesdurationr2   c             C   sT   yt || _W n tk
r(   || _Y nX || _|| _t|| _t|| _|| _d S )N)	r   r   r   r   r   r   rJ   rK   r   )rb   r   r   r   r   r>   r>   r?   r     s    


zRunResult.__init__)r2   c             C   s$   d| j t| jjt| jj| jf S )NzK<RunResult ret=%s len(stdout.lines)=%d len(stderr.lines)=%d duration=%.2fs>)r   rx   rJ   r   rK   r   )rb   r>   r>   r?   r     s    zRunResult.__repr__c             C   s   |  | jS )aU  Return a dictionary of outcome noun -> count from parsing the terminal
        output that the test process produced.

        The returned nouns will always be in plural form::

            ======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====

        Will return ``{"failed": 1, "passed": 1, "warnings": 1, "errors": 1}``.
        )parse_summary_nounsr   )rb   r>   r>   r?   parseoutcomes  s    
zRunResult.parseoutcomesc                s^   x<t |D ](}t|r
t|}dd |D }P q
W tdddd  fdd| D S )a  Extract the nouns from a pytest terminal summary line.

        It always returns the plural noun for consistency::

            ======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====

        Will return ``{"failed": 1, "passed": 1, "warnings": 1, "errors": 1}``.
        c             S   s   i | ]\}}t ||qS r>   )r   )rl   countZnounr>   r>   r?   
<dictcomp>-  s    z1RunResult.parse_summary_nouns.<locals>.<dictcomp>z(Pytest terminal summary report not foundwarningserrors)warningr~   c                s   i | ]\}}|  ||qS r>   )get)rl   kv)	to_pluralr>   r?   r   6  s    )reversedrex_session_durationsearchrex_outcomefindallr   items)clsr   rN   r   r   r>   )r   r?   r      s    


zRunResult.parse_summary_nounsr   )r   r   r   r   xpassedxfailedr2   c       
   	   C   s2   d}ddl m} |  }	||	||||||d dS )zAssert that the specified outcomes appear with the respective
        numbers (0 means it didn't occur) in the text output from a test run.Tr   )assert_outcomes)r   r   r   r   r   r   N)r   r   r   )
rb   r   r   r   r   r   r   r   r   r   r>   r>   r?   r   8  s    zRunResult.assert_outcomes)r   r   r   r   r   r   )r   r   r   r   r   r   r   r
   rY   floatr   r   r   r   classmethodr   r   r>   r>   r>   r?   r     s"   
     r   c               @   s(   e Zd ZddddZddddZdS )CwdSnapshotN)r2   c             C   s   t  | _d S )N)rZ   getcwd_CwdSnapshot__saved)rb   r>   r>   r?   r   S  s    zCwdSnapshot.__init__c             C   s   t | j d S )N)rZ   chdirr  )rb   r>   r>   r?   r   V  s    zCwdSnapshot.restore)r   r   r   r   r   r>   r>   r>   r?   r  R  s   r  c               @   s:   e Zd Zdeeegef  ddddZddddZdS )	r   N)preserver2   c             C   s   || _ ttj| _d S )N)_SysModulesSnapshot__preservedictru   modules_SysModulesSnapshot__saved)rb   r  r>   r>   r?   r   [  s    zSysModulesSnapshot.__init__)r2   c                sB    j r& j fddtj D  tj  tj j d S )Nc             3   s$   | ]\}}  |r||fV  qd S )N)r  )rl   r   m)rb   r>   r?   rq   b  s    z-SysModulesSnapshot.restore.<locals>.<genexpr>)r  r  r   ru   r
  r   r   )rb   r>   )rb   r?   r   _  s
    
zSysModulesSnapshot.restore)N)	r   r   r   r   r   rY   r^   r   r   r>   r>   r>   r?   r   Z  s    r   c               @   s(   e Zd ZddddZddddZdS )r   N)r2   c             C   s   t tjt tjf| _d S )N)r   ru   path	meta_path_SysPathsSnapshot__saved)rb   r>   r>   r?   r   i  s    zSysPathsSnapshot.__init__c             C   s"   | j \tjd d < tjd d < d S )N)r  ru   r  r  )rb   r>   r>   r?   r   l  s    zSysPathsSnapshot.restore)r   r   r   r   r   r>   r>   r>   r?   r   h  s   r   c               @   s  e Zd ZdZdZeZG dd deZdde	e
edddd	Zeed
ddZed
ddZdd
ddZed
ddZeedddZdd
ddZdeeeeef  eeef eedddZeeeedddZeedd d!Z eedd"d#Z!ee"dd$d%Z#eedd&d'Z$ed
d(d)Z%ed
d*d+Z&de'eed,f  dd-d.d/Z(eed0d1d2Z)eed0d3d4Z*de'e ed0d5d6Z+e,Z,e-eed,f e'ee.e/f  d7d8d9Z0eed,f d:d;d<Z1eee/e.f  e2e/ d=d>d?Z3eedd@dAZ4eeddBdCZ5e6e2e/ ef d
dDdEZ7dFddGeed,f eedHdIdJZ8eed,f ee9dKdLdMZ:eed,f ee9dKdNdOZ;eeed,f  e2eed,f  dPdQdRZ<eed,f e-dPdSdTZ=eed,f e-dPdUdVZ>deee/dXdYdZZ?ee2e/ dd[d\Z@ddd]eeef ed^d_d`ZAe.ee'ee/e.f  dadbdcZBeCjDeCjDefeeEeFf eeEeFf dddedfZGdedgeed,f e'eH e9dhdidjZIdkdl ZJe6edmf d
dndoZKe9d
dpdqZLdrds ZMddte'eH e9dudvdwZNdeeHdydzd{d|ZOdeeHdyd}d~dZPdS )r   a  
    Facilities to write tests/configuration files, execute pytest in isolation, and match
    against expected output, perfect for black-box testing of pytest plugins.

    It attempts to isolate the test run from external factors as much as possible, modifying
    the current working directory to ``path`` and environment variables during initialization.

    Attributes:

    :ivar Path path: temporary directory path used to create files/run tests from, etc.

    :ivar plugins:
       A list of plugins to use with :py:meth:`parseconfig` and
       :py:meth:`runpytest`.  Initially this is an empty list but plugins can
       be added to the list.  The type of items to add to the list depends on
       the method using them so refer to them for details.
    Fc               @   s   e Zd ZdS )zPytester.TimeoutExpiredN)r   r   r   r>   r>   r>   r?   TimeoutExpired  s   r  )r   N)r   r   r   r2   c            C   s  t | || _t | _|jr&|jj}n|jj}|| _|j	|dd| _
g | _t | _t | _|  | _|   | j| j | jjd| _|j	d| dd| _t  | _}|dt| j |jddd |jd	dd t| j}|d
| |d| |dd d S )NT)Znumberedz--runpytestztmp-ZPYTEST_DEBUG_TEMPROOTZTOX_ENV_DIRF)ZraisingZPYTEST_ADDOPTSHOMEUSERPROFILEZ	PY_COLORS0)r!   r   r   _mod_collectionsfunctionr   noder   r   mktemp_pathpluginsr  _cwd_snapshotr   _sys_path_snapshot$_Pytester__take_sys_modules_snapshot_sys_modules_snapshotr  r   	_finalizerA   Z	getoption_method_test_tmprootr%   _monkeypatchZsetenvrY   Zdelenvr  )rb   r   r   r   r   mpZtmphomer>   r>   r?   r     s0    


zPytester.__init__)r2   c             C   s   | j S )zCTemporary directory where files are created and pytest is executed.)r  )rb   r>   r>   r?   r    s    zPytester.pathc             C   s   d| j dS )Nz
<Pytester >)r  )rb   r>   r>   r?   r     s    zPytester.__repr__c             C   s,   | j   | j  | j  | j  dS )a  
        Clean up global state artifacts.

        Some methods modify the global interpreter state and this tries to
        clean this up. It does not remove the temporary directory however so
        it can be looked at after the test run has finished.
        N)r  r   r  r  r!  Zundo)rb   r>   r>   r?   r    s    


zPytester._finalizec             C   s   dd }t |dS )Nc             S   s
   |  dS )N)Zzopereadline)rR   )r   r>   r>   r?   preserve_module  s    z=Pytester.__take_sys_modules_snapshot.<locals>.preserve_module)r  )r   )rb   r%  r>   r>   r?   Z__take_sys_modules_snapshot  s    z$Pytester.__take_sys_modules_snapshot)rF   r2   c             C   s    t | |_}| j|j |S )z:Create a new :py:class:`HookRecorder` for a PluginManager.)r   reprecr   r   r   )rb   rF   r&  r>   r>   r?   make_hook_recorder  s    zPytester.make_hook_recorderc             C   s   t | j dS )zaCd into the temporary directory.

        This is done automatically upon instantiation.
        N)rZ   r  r  )rb   r>   r>   r?   r    s    zPytester.chdirutf-8)extr   filesencodingr2   c                s   t | }tttf td fdd|rZdfdd|D }| j}|d||f d }xr|D ]j\}}	| j	
||}
|
jjddd	 t|	}dfd
d|jD }|
j|  d |d krd|
}qdW |d k	st|S )N)sr2   c                s   t | tr|  S t| S )N)r   bytesdecoderY   )r,  )r+  r>   r?   to_text  s    z#Pytester._makefile.<locals>.to_textrT   c             3   s   | ]} |V  qd S )Nr>   )rl   r   )r/  r>   r?   rq     s    z%Pytester._makefile.<locals>.<genexpr>r   T)parentsexist_okc             3   s   | ]} |V  qd S )Nr>   )rl   rN   )r/  r>   r?   rq     s    )r+  )r   r   r   r   r-  rY   r{   r   insertr  joinpathwith_suffixparentmkdirr   r   
write_textstripr   )rb   r)  r   r*  r+  r   sourcebasenamer   valuepZsource_r>   )r+  r/  r?   	_makefile  s"    zPytester._makefile)r)  argsr   r2   c             O   s   |  |||S )a  Create new file(s) in the test directory.

        :param str ext:
            The extension the file(s) should use, including the dot, e.g. `.py`.
        :param args:
            All args are treated as strings and joined using newlines.
            The result is written as contents to the file.  The name of the
            file is based on the test function requesting this fixture.
        :param kwargs:
            Each keyword is the name of a file, while the value of it will
            be written as contents of the file.

        Examples:

        .. code-block:: python

            pytester.makefile(".txt", "line1", "line2")

            pytester.makefile(".ini", pytest="[pytest]\naddopts=-rs\n")

        )r=  )rb   r)  r>  r   r>   r>   r?   makefile  s    zPytester.makefile)r9  r2   c             C   s   | j |dS )z2Write a contest.py file with 'source' as contents.)Zconftest)
makepyfile)rb   r9  r>   r>   r?   makeconftest  s    zPytester.makeconftestc             C   s   | j d|dS )z/Write a tox.ini file with 'source' as contents.z.ini)Ztox)r?  )rb   r9  r>   r>   r?   makeini  s    zPytester.makeinic             C   s   |  |}tt|d S )z7Return the pytest section from the tox.ini config file.Zpytest)rB  r   rY   )rb   r9  r<  r>   r>   r?   	getinicfg  s    
zPytester.getinicfgc             C   s   | j d|dS )z^Write a pyproject.toml file with 'source' as contents.

        .. versionadded:: 6.0
        z.toml)	pyproject)r?  )rb   r9  r>   r>   r?   makepyprojecttoml#  s    zPytester.makepyprojecttomlc             O   s   |  d||S )aS  Shortcut for .makefile() with a .py extension.

        Defaults to the test name with a '.py' extension, e.g test_foobar.py, overwriting
        existing files.

        Examples:

        .. code-block:: python

            def test_something(pytester):
                # Initial file is created test_something.py.
                pytester.makepyfile("foobar")
                # To create multiple files, pass kwargs accordingly.
                pytester.makepyfile(custom="foobar")
                # At this point, both 'test_something.py' & 'custom.py' exist in the test directory.

        z.py)r=  )rb   r>  r   r>   r>   r?   r@  *  s    zPytester.makepyfilec             O   s   |  d||S )a[  Shortcut for .makefile() with a .txt extension.

        Defaults to the test name with a '.txt' extension, e.g test_foobar.txt, overwriting
        existing files.

        Examples:

        .. code-block:: python

            def test_something(pytester):
                # Initial file is created test_something.txt.
                pytester.maketxtfile("foobar")
                # To create multiple files, pass kwargs accordingly.
                pytester.maketxtfile(custom="foobar")
                # At this point, both 'test_something.txt' & 'custom.txt' exist in the test directory.

        z.txt)r=  )rb   r>  r   r>   r>   r?   maketxtfile>  s    zPytester.maketxtfilezos.PathLike[str])r  r2   c             C   s"   |dkr| j }| jt| dS )zPrepend a directory to sys.path, defaults to :py:attr:`tmpdir`.

        This is undone automatically when this object dies at the end of each
        test.
        N)r  r!  Zsyspath_prependrY   )rb   r  r>   r>   r?   syspathinsertR  s    zPytester.syspathinsert)r   r2   c             C   s   | j | }|  |S )zCreate a new (sub)directory.)r  r6  )rb   r   r<  r>   r>   r?   r6  _  s    
zPytester.mkdirc             C   s$   | j | }|  |d  |S )zCreate a new python package.

        This creates a (sub)directory with an empty ``__init__.py`` file so it
        gets recognised as a Python package.
        z__init__.py)r  r6  r3  touch)rb   r   r<  r>   r>   r?   mkpydire  s    
zPytester.mkpydirc       	      C   s2  | j jd}|dkrtdtt| j jj| }x,| j jdD ]}|j	sRt
|j|j	 }qDW |dkr| j}|| }||d  }| r|}q| r|}qt| d| n
||}| r|d stj|tj| j | jS | r| j|j}t|| |S td| d	dS )
zCopy file from project's directory into the testdir.

        :param str name: The name of the file to copy.
        :return: path to the copied directory (inside ``self.path``).

        r=   Nz2pytester_example_dir is unset, can't copy examplesZpytester_example_pathz.pyz( can't be found as module or package in z__init__.pyz	example "z%" is not found as a file or directory)r   rA   Zgetinir   r   rY   rootdirr  Ziter_markersr>  r   r3  r   is_diris_fileLookupErrorpyr  localr   r   shutil)	rb   r   Zexample_dirZextra_element	func_nameZ	maybe_dirZ
maybe_fileZexample_pathresultr>   r>   r?   copy_examplep  s6    


zPytester.copy_example)rA   argr2   c             C   sb   t |}dt|ksttj|}|jj|d |j	t|gddd }|jj
|tjd |S )a  Return the collection node of a file.

        :param _pytest.config.Config config:
           A pytest config.
           See :py:meth:`parseconfig` and :py:meth:`parseconfigure` for creating it.
        :param py.path.local arg:
            Path to the file.
        z::)sessionF)genitemsr   )rU  
exitstatus)r$   from_configrY   r   rN  r  rO  r   pytest_sessionstartperform_collectpytest_sessionfinishr   OK)rb   rA   rT  rU  r<  resr>   r>   r?   getnode  s    
zPytester.getnode)r  c             C   sd   t j|}| |}t|}|j|}|jj	|d |j
|gddd }|jj|tjd |S )zReturn the collection node of a file.

        This is like :py:meth:`getnode` but uses :py:meth:`parseconfigure` to
        create the (configured) pytest Config instance.

        :param py.path.local path: Path to the file.
        )rU  F)rV  r   )rU  rW  )rN  r  rO  parseconfigurer$   rX  fspathZbestrelpathr   rY  rZ  r[  r   r\  )rb   r  rA   rU  r   r]  r>   r>   r?   getpathnode  s    

zPytester.getpathnode)colitemsr2   c             C   s0   |d j }g }x|D ]}||| qW |S )zGenerate all test items from a collection node.

        This recurses into the collection node and returns a list of all the
        test items contained within.
        r   )rU  r   rV  )rb   rb  rU  rR  colitemr>   r>   r?   rV    s
    

zPytester.genitemsc             C   s"   |  |}| jj}| }||S )a'  Run the "test_func" Item.

        The calling test instance (class containing the test method) must
        provide a ``.getrunner()`` method which should return a runner which
        can run the test protocol for a single item, e.g.
        :py:func:`_pytest.runner.runtestprotocol`.
        )getitemr   instanceZ	getrunner)rb   r9  rj   Ztestclassinstancerunnerr>   r>   r?   runitem  s    	
zPytester.runitemc             G   s"   |  |}t||g }| j| S )a  Run a test module in process using ``pytest.main()``.

        This run writes "source" into a temporary file and runs
        ``pytest.main()`` on it, returning a :py:class:`HookRecorder` instance
        for the result.

        :param source: The source code of the test module.

        :param cmdlineargs: Any extra command line arguments to use.

        :returns: :py:class:`HookRecorder` instance of the result.
        )r@  r   
inline_run)rb   r9  cmdlineargsr<  r   r>   r>   r?   inline_runsource  s    
zPytester.inline_runsourcec             G   s*   | j d| }dd |dD }||fS )a!  Run ``pytest.main(['--collectonly'])`` in-process.

        Runs the :py:func:`pytest.main` function to run all of pytest inside
        the test process itself like :py:meth:`inline_run`, but returns a
        tuple of the collected items and a :py:class:`HookRecorder` instance.
        --collect-onlyc             S   s   g | ]
}|j qS r>   )rj   )rl   r   r>   r>   r?   rp     s    z,Pytester.inline_genitems.<locals>.<listcomp>Zpytest_itemcollected)rk  )rh  r   )rb   r>  recr   r>   r>   r?   inline_genitems  s    zPytester.inline_genitemsr>   )r  no_reraise_ctrlc)r>  rn  r2   c      
         s   t   t|}g }z| j |t j g  G  fddd}||  tdd |D |d}t dkr 	 }nG dd d}||_
|tjkr|s|d	}|r|d
 jjtkrt |S x|D ]
}	|	  qW X dS )a%  Run ``pytest.main()`` in-process, returning a HookRecorder.

        Runs the :py:func:`pytest.main` function to run all of pytest inside
        the test process itself.  This means it can return a
        :py:class:`HookRecorder` instance which gives more detailed results
        from that run than can be done by matching stdout/stderr from
        :py:meth:`runpytest`.

        :param args:
            Command line arguments to pass to :py:func:`pytest.main`.
        :param plugins:
            Extra plugin instances the ``pytest.main()`` instance should use.
        :param no_reraise_ctrlc:
            Typically we reraise keyboard interrupts from the child run. If
            True, the KeyboardInterrupt exception is captured.

        :returns: A :py:class:`HookRecorder` instance.
        c                   s"   e Zd Zedd fddZdS )z$Pytester.inline_run.<locals>.CollectN)rA   r2   c                s     |j d S )N)ra   r'  rF   )r   rA   )rl  rb   r>   r?   rI   ,  s    z5Pytester.inline_run.<locals>.Collect.pytest_configure)r   r   r   r   rI   r>   )rl  rb   r>   r?   Collect+  s   ro  c             S   s   g | ]}t |qS r>   )rY   )rl   r   r>   r>   r?   rp   0  s    z'Pytester.inline_run.<locals>.<listcomp>)r  rV   c               @   s   e Zd ZdS )z#Pytester.inline_run.<locals>.reprecN)r   r   r   r>   r>   r>   r?   r&  5  s   r&  Zpytest_keyboard_interruptN)	importlibinvalidate_cachesr   ra   r  r   r   r   rx   r   r   r   ZINTERRUPTEDr   excinfotypeKeyboardInterrupt)
rb   r  rn  r>  Z
finalizersro  r   r&  r   	finalizerr>   )rl  rb   r?   rh    s*    


zPytester.inline_run)r>  r   r2   c             O   s:  | dd}|r|   t }td}|  zy| j||}W n tk
r } zD|jd }yt	|jd }W n t
k
r   Y nX G dd d}W dd}~X Y n* tk
r   t  G dd d}Y nX W d| \}	}
|  tj|	 tj|
 X |jdk	stt|j|	 |
 t | }||_|S )	ztReturn result of running pytest in-process, providing a similar
        interface to what self.runpytest() provides.rG  Fru   r   c               @   s   e Zd ZeZdS )z,Pytester.runpytest_inprocess.<locals>.reprecN)r   r   r   r   r>   r>   r>   r?   r&  [  s   r&  Nc               @   s   e Zd ZedZdS )z,Pytester.runpytest_inprocess.<locals>.reprec   N)r   r   r   r   r   r>   r>   r>   r?   r&  a  s   )r   rG  r   timer   Zstart_capturingrh  
SystemExitr>  r   r   	Exception	traceback	print_excZ
readouterrZstop_capturingru   rJ   writerK   r   r   r   
splitlinesr&  )rb   r>  r   rG  nowcapturer&  er   rc   errr]  r>   r>   r?   runpytest_inprocessE  s8    
zPytester.runpytest_inprocessc             O   sJ   |  |}| jdkr | j||S | jdkr6| j||S td| j dS )zRun pytest inline or in a subprocess, depending on the command line
        option "--runpytest" and return a :py:class:`RunResult`.r9   r;   zUnrecognized runpytest option: N)_ensure_basetempr  r  runpytest_subprocessRuntimeError)rb   r>  r   new_argsr>   r>   r?   r:   q  s    


zPytester.runpytest)r>  r2   c             C   sB   t |}x4|D ]}t|drP qW |d| jjd  |S )Nz
--basetempz--basetemp=%sbasetemp)r   rY   rR   ra   r  r5  r3  )rb   r>  r  r   r>   r>   r?   r  }  s    
zPytester._ensure_basetempc             G   sB   ddl }| |}dd |D }|j|| j}| j|j |S )a  Return a new pytest Config instance from given commandline args.

        This invokes the pytest bootstrapping code in _pytest.config to create
        a new :py:class:`_pytest.core.PluginManager` and call the
        pytest_cmdline_parse hook to create a new
        :py:class:`_pytest.config.Config` instance.

        If :py:attr:`plugins` has been populated they should be plugin modules
        to be registered with the PluginManager.
        r   Nc             S   s   g | ]}t |qS r>   )rY   )rl   r   r>   r>   r?   rp     s    z(Pytester.parseconfig.<locals>.<listcomp>)r   r  rA   Z_prepareconfigr  r   r   r   )rb   r>  r   r  rA   r>   r>   r?   parseconfig  s    
zPytester.parseconfigc             G   s   | j | }|  |S )zReturn a new pytest configured Config instance.

        Returns a new :py:class:`_pytest.config.Config` instance like
        :py:meth:`parseconfig`, but also calls the pytest_configure hook.
        )r  Z_do_configure)rb   r>  rA   r>   r>   r?   r_    s    
zPytester.parseconfigure	test_func)r9  funcnamer2   c             C   s@   |  |}x|D ]}|j|kr|S qW ds<td|||dS )ax  Return the test item for a test function.

        Writes the source to a python file and runs pytest's collection on
        the resulting module, returning the test item for the requested
        function name.

        :param source:
            The module source.
        :param funcname:
            The name of the test function for which to return a test item.
        r   z+{!r} item not found in module:
{}
items: {}N)getitemsr   r   r   )rb   r9  r  r   rj   r>   r>   r?   rd    s    



zPytester.getitemc             C   s   |  |}| |gS )zReturn all test items collected from the module.

        Writes the source to a Python file and runs pytest's collection on
        the resulting module, returning all test items contained within.
        )getmodulecolrV  )rb   r9  modcolr>   r>   r?   r    s    
zPytester.getitems)withinit)r9  r  c            C   sp   t |tr$| j|}|r>tdn| jt|i}| jf |}|rN| jdd | j|f|  | _	}| 
||S )a*  Return the module collection node for ``source``.

        Writes ``source`` to a file using :py:meth:`makepyfile` and then
        runs the pytest collection on it, returning the collection node for the
        test module.

        :param source:
            The source code of the module to collect.

        :param configargs:
            Any extra arguments to pass to :py:meth:`parseconfigure`.

        :param withinit:
            Whether to also write an ``__init__.py`` file to the same
            directory to ensure it is a package.
        znot supported for paths#)r   )r   r   r  r3  r   r   rY   r@  r_  rA   r^  )rb   r9  
configargsr  r  kwrA   r>   r>   r?   r    s    
zPytester.getmodulecol)r  r   r2   c             C   sB   || j krt| | j |< x | j | D ]}|j|kr(|S q(W dS )a-  Return the collection node for name from the module collection.

        Searchs a module collection node for a collection node matching the
        given name.

        :param modcol: A module collection node; see :py:meth:`getmodulecol`.
        :param name: The name of the node to return.
        N)r  r   rw   r   )rb   r  r   rc  r>   r>   r?   collect_by_name  s    

zPytester.collect_by_name)rJ   rK   c          	   K   s   t j }t jtdt  |ddg|d< ||d< || jkrNt	j
|d< nt|trdt	j
|d< n||d< t	j|f||d|}|| jkr|jdk	st|j  n$t|tr|jdk	st|j| |S )zInvoke subprocess.Popen.

        Calls subprocess.Popen making sure the current working directory is
        in the PYTHONPATH.

        You probably want to use :py:meth:`run` instead.
        N
PYTHONPATHr   envstdin)rJ   rK   )rZ   environr   pathsepr{   filterr  r   CLOSE_STDINr;   r\   r   r-  Popenr  r   closer}  )rb   cmdargsrJ   rK   r  r  r  popenr>   r>   r?   r    s"    
 



zPytester.popen)timeoutr  )r  r  r2   c         
      s  d}t dd  D  jd}jd}td   tdt  |jdd	d
}|jdd	d
}t }	j	 |||t
jdkdjdk	rj  dd fdd}
dkrȈ }n,y}W n tjk
r   |
  Y nX W dQ R X W dQ R X |jd	d
6}|jd	d
}|  }|  }W dQ R X W dQ R X |t
j |t
j tt t|}W dQ R X t|||t |	 S )a  Run a command with arguments.

        Run a process using subprocess.Popen saving the stdout and stderr.

        :param cmdargs:
            The sequence of arguments to pass to `subprocess.Popen()`, with path-like objects
            being converted to ``str`` automatically.
        :param timeout:
            The period in seconds after which to timeout and raise
            :py:class:`Pytester.TimeoutExpired`.
        :param stdin:
            Optional standard input.  Bytes are being send, closing
            the pipe, otherwise it is passed through to ``popen``.
            Defaults to ``CLOSE_STDIN``, which translates to using a pipe
            (``subprocess.PIPE``) that gets closed.

        :rtype: RunResult
        Tc             s   s(   | ] }t |tjrt|n|V  qd S )N)r   rZ   PathLiker`  )rl   rT  r>   r>   r?   rq   9  s    zPytester.run.<locals>.<genexpr>rJ   rK   running:z     in:wutf8)r+  win32)r  rJ   rK   	close_fdsN)r2   c                 s0   d} dj  d}    |d S )NTz3{seconds} second timeout expired running: {command})secondscommand)r   killwaitr  )r   Ztimeout_message)r  r  rb   r  r>   r?   handle_timeoutL  s    
z$Pytester.run.<locals>.handle_timeout)r  )tupler  r3  r   r   rQ   openr   rx  r  ru   platformr  r  r  r;   r  readr~  _dump_linesrJ   rK   
contextlibsuppressr   r   r   )rb   r  r  r  r   p1p2f1f2r  r  r   rc   r  r>   )r  r  rb   r  r?   rX     s@     


  zPytester.runc             C   sH   yx|D ]}t ||d qW W n$ tk
rB   t d| d Y nX d S )N)filezcouldn't print to z because of encoding)r   UnicodeEncodeError)rb   r   fprN   r>   r>   r?   r  k  s
    
zPytester._dump_lines.c             C   s
   t jdfS )Nz-mpytest)ru   
executable)rb   r>   r>   r?   _getpytestargsr  s    zPytester._getpytestargsc             C   s   |  tj|S )z\Run a python script using sys.executable as interpreter.

        :rtype: RunResult
        )rX   ru   r  )rb   scriptr>   r>   r?   	runpythonu  s    zPytester.runpythonc             C   s   |  tjd|S )z<Run python -c "command".

        :rtype: RunResult
        z-c)rX   ru   r  )rb   r  r>   r>   r?   runpython_c|  s    zPytester.runpython_c)r  )r  r2   c            G   sb   d}t | jddd}d| f| }dd | jD }|rFd|d	 f| }|  | }| j|d
|iS )a  Run pytest as a subprocess with given arguments.

        Any plugins added to the :py:attr:`plugins` list will be added using the
        ``-p`` command line option.  Additionally ``--basetemp`` is used to put
        any temporary files and directories in a numbered directory prefixed
        with "runpytest-" to not conflict with the normal numbered pytest
        location for temporary files and directories.

        :param args:
            The sequence of arguments to pass to the pytest subprocess.
        :param timeout:
            The period in seconds after which to timeout and raise
            :py:class:`Pytester.TimeoutExpired`.

        :rtype: RunResult
        Tz
runpytest-i  )rootprefixmodez--basetemp=%sc             S   s   g | ]}t |tr|qS r>   )r   rY   )rl   r   r>   r>   r?   rp     s    z1Pytester.runpytest_subprocess.<locals>.<listcomp>z-pr   r  )r+   r  r  r  rX   )rb   r  r>  r   r<  r  r>   r>   r?   r    s    zPytester.runpytest_subprocess      $@zpexpect.spawn)stringexpect_timeoutr2   c             C   sL   | j d }|jdd dtt|  }| d| d| }| j||dS )zRun pytest using pexpect.

        This makes sure to use the right pytest and sets up the temporary
        directory locations.

        The pexpect child is returned.
        ztemp-pexpecti  )r   z --basetemp=)r  )r  r6  r{   maprY   r  spawn)rb   r  r  r  Zinvokecmdr>   r>   r?   spawn_pytest  s
    

zPytester.spawn_pytest)r  r  r2   c             C   sn   t dd}ttdr(dt kr(td t|ds:td | jdd	}|j	|||d
}| j
|j |S )zMRun a command using pexpect.

        The pexpect child is returned.
        pexpectz3.0rk   Z64zpypy-64 bit not supportedr  zpexpect.spawn not availablez	spawn.outwb)logfiler  )r)   rt   ru   r  machiner*   r  r3  r  r  r   r   r  )rb   r  r  r  r  childr>   r>   r?   r    s    

zPytester.spawn)r(  )N)N)r  )r>   )r  )r  )Qr   r   r   r   __test__objectr  rz  r  r#   r.   r^   r   propertyr   r  rY   r   r  r   r  r   r   r'  r  r   r   r   r-  r   r=  r?  rA  rB  r   rC  rE  r@  rF  r   rG  r6  rI  rS  r$   r   r&   r'   r^  ra  r
   rV  rg  rj  r   rm  rh  r   r  r:   r  r  r_  rd  r  r  r  r;   r\   r   r   r  r  rX   r  r  r  r  r  r  r  r>   r>   r>   r?   r   p  s   "/ E+	

 $$Jc               @   s.   e Zd ZddddZee ddddZdS )r   N)r2   c             C   s   t  | _d S )N)r   stringio)rb   r>   r>   r?   r     s    zLineComp.__init__)r}   r2   c             C   sB   d}| j  }| j d | j d |d}t|| dS )zAssert that ``lines2`` are contained (linearly) in :attr:`stringio`'s value.

        Lines are matched using :func:`LineMatcher.fnmatch_lines`.
        Tr   rT   N)r  rC   truncateseekr_   r   fnmatch_lines)rb   r}   r   valr|   r>   r>   r?   assert_contains_lines  s    

zLineComp.assert_contains_lines)r   r   r   r   r   rY   r  r>   r>   r>   r?   r     s   F)r   rY   initc               @   s$  e Zd ZdZdZejZejZejZddee	ddddZ
eejjdd	d
ZeejjdddZedd Zedd Zejdd ZeedddZedddZddddZddddZejjdddZejjdddZejjdddZeed d!d"Zejjdd#d$Z ejjdd%d&Z!ejjdd'd(Z"doddd)d*Z#ejjdd+d,Z$ejjdd-d.Z%dpejjdd/d0Z&e'e(e)e*e+f  d1d2d3Z,d4d5 Z-e.e)e*e+f  e.e* d6d7d8Z/d9d: Z0d;d< Z1d=d> Z2d?dd@e	dAdBdCZ3e4ddDdEZ5e4ddFdGZ6e'ddHdIZ7e'ddJdKZ8dqdMdNZ9dOdP Z:drdQdRZ;e+ee(e)e*e+f  dSdTdUZ<e=j>e=j>efe)e?e@f e)e?e@f dVdWdXZAdedYe4ddZd[ZBe4dd\d]ZCd^d_ ZDdd`e4ddadbZEdseeFdddedfdgZGdteeFdddhdidjZHeddkdlZIeddmdnZJdS )ur   z
    Similar to :class:`Pytester`, but this class works with legacy py.path.local objects instead.

    All methods just forward to an internal :class:`Pytester` instance, converting results
    to `py.path.local` objects as necessary.
    F)r   N)r   r   r2   c            C   s   t | || _d S )N)r!   	_pytester)rb   r   r   r>   r>   r?   r     s    zTestdir.__init__)r2   c             C   s   t j| jjS )z-Temporary directory where tests are executed.)rN  r  rO  r  )rb   r>   r>   r?   tmpdir  s    zTestdir.tmpdirc             C   s   t j| jjS )N)rN  r  rO  r  r   )rb   r>   r>   r?   test_tmproot  s    zTestdir.test_tmprootc             C   s   | j jS )N)r  r   )rb   r>   r>   r?   r     s    zTestdir.requestc             C   s   | j jS )N)r  r  )rb   r>   r>   r?   r    s    zTestdir.pluginsc             C   s   || j _d S )N)r  r  )rb   r  r>   r>   r?   r    s    c             C   s   | j jS )N)r  r!  )rb   r>   r>   r?   monkeypatch  s    zTestdir.monkeypatchc             C   s   | j |S )z(See :meth:`Pytester.make_hook_recorder`.)r  r'  )rb   rF   r>   r>   r?   r'    s    zTestdir.make_hook_recorderc             C   s
   | j  S )zSee :meth:`Pytester.chdir`.)r  r  )rb   r>   r>   r?   r    s    zTestdir.chdirc             C   s
   | j  S )zSee :meth:`Pytester._finalize`.)r  r  )rb   r>   r>   r?   finalize  s    zTestdir.finalizec             O   s    t jt| jj|f||S )zSee :meth:`Pytester.makefile`.)rN  r  rO  rY   r  r?  )rb   r)  r>  r   r>   r>   r?   r?  	  s    zTestdir.makefilec             C   s   t jt| j|S )z"See :meth:`Pytester.makeconftest`.)rN  r  rO  rY   r  rA  )rb   r9  r>   r>   r?   rA    s    zTestdir.makeconftestc             C   s   t jt| j|S )zSee :meth:`Pytester.makeini`.)rN  r  rO  rY   r  rB  )rb   r9  r>   r>   r?   rB    s    zTestdir.makeini)r9  r2   c             C   s   | j |S )zSee :meth:`Pytester.getinicfg`.)r  rC  )rb   r9  r>   r>   r?   rC    s    zTestdir.getinicfgc             C   s   t jt| j|S )z'See :meth:`Pytester.makepyprojecttoml`.)rN  r  rO  rY   r  rE  )rb   r9  r>   r>   r?   rE    s    zTestdir.makepyprojecttomlc             O   s   t jt| jj||S )z See :meth:`Pytester.makepyfile`.)rN  r  rO  rY   r  r@  )rb   r>  r   r>   r>   r?   r@    s    zTestdir.makepyfilec             O   s   t jt| jj||S )z!See :meth:`Pytester.maketxtfile`.)rN  r  rO  rY   r  rF  )rb   r>  r   r>   r>   r?   rF  !  s    zTestdir.maketxtfilec             C   s   | j |S )z#See :meth:`Pytester.syspathinsert`.)r  rG  )rb   r  r>   r>   r?   rG  %  s    zTestdir.syspathinsertc             C   s   t jt| j|S )zSee :meth:`Pytester.mkdir`.)rN  r  rO  rY   r  r6  )rb   r   r>   r>   r?   r6  )  s    zTestdir.mkdirc             C   s   t jt| j|S )zSee :meth:`Pytester.mkpydir`.)rN  r  rO  rY   r  rI  )rb   r   r>   r>   r?   rI  -  s    zTestdir.mkpydirc             C   s   t jt| j|S )z"See :meth:`Pytester.copy_example`.)rN  r  rO  rY   r  rS  )rb   r   r>   r>   r?   rS  1  s    zTestdir.copy_example)rA   r2   c             C   s   | j ||S )zSee :meth:`Pytester.getnode`.)r  r^  )rb   rA   rT  r>   r>   r?   r^  5  s    zTestdir.getnodec             C   s   | j |S )z!See :meth:`Pytester.getpathnode`.)r  ra  )rb   r  r>   r>   r?   ra  9  s    zTestdir.getpathnode)rb  r2   c             C   s   | j |S )zSee :meth:`Pytester.genitems`.)r  rV  )rb   rb  r>   r>   r?   rV  =  s    zTestdir.genitemsc             C   s   | j |S )zSee :meth:`Pytester.runitem`.)r  rg  )rb   r9  r>   r>   r?   rg  A  s    zTestdir.runitemc             G   s   | j j|f| S )z&See :meth:`Pytester.inline_runsource`.)r  rj  )rb   r9  ri  r>   r>   r?   rj  E  s    zTestdir.inline_runsourcec             G   s   | j j| S )z%See :meth:`Pytester.inline_genitems`.)r  rm  )rb   r>  r>   r>   r?   rm  I  s    zTestdir.inline_genitemsr>   )r  rn  )rn  c            G   s   | j j|||dS )z See :meth:`Pytester.inline_run`.)r  rn  )r  rh  )rb   r  rn  r>  r>   r>   r?   rh  M  s    zTestdir.inline_runc             O   s   | j j||S )z)See :meth:`Pytester.runpytest_inprocess`.)r  r  )rb   r>  r   r>   r>   r?   r  S  s    zTestdir.runpytest_inprocessc             O   s   | j j||S )zSee :meth:`Pytester.runpytest`.)r  r:   )rb   r>  r   r>   r>   r?   r:   W  s    zTestdir.runpytestc             G   s   | j j| S )z!See :meth:`Pytester.parseconfig`.)r  r  )rb   r>  r>   r>   r?   r  [  s    zTestdir.parseconfigc             G   s   | j j| S )z$See :meth:`Pytester.parseconfigure`.)r  r_  )rb   r>  r>   r>   r?   r_  _  s    zTestdir.parseconfigurer  c             C   s   | j ||S )zSee :meth:`Pytester.getitem`.)r  rd  )rb   r9  r  r>   r>   r?   rd  c  s    zTestdir.getitemc             C   s   | j |S )zSee :meth:`Pytester.getitems`.)r  r  )rb   r9  r>   r>   r?   r  g  s    zTestdir.getitemsc             C   s   | j j|||dS )z"See :meth:`Pytester.getmodulecol`.)r  r  )r  r  )rb   r9  r  r  r>   r>   r?   r  k  s    zTestdir.getmodulecol)r  r   r2   c             C   s   | j ||S )z%See :meth:`Pytester.collect_by_name`.)r  r  )rb   r  r   r>   r>   r?   r  q  s    zTestdir.collect_by_name)rJ   rK   c             K   s   | j j||||f|S )zSee :meth:`Pytester.popen`.)r  r  )rb   r  rJ   rK   r  r  r>   r>   r?   r  w  s    	zTestdir.popen)r  r  c            G   s   | j j|||dS )zSee :meth:`Pytester.run`.)r  r  )r  rX   )rb   r  r  r  r>   r>   r?   rX     s    zTestdir.runc             C   s   | j |S )zSee :meth:`Pytester.runpython`.)r  r  )rb   r  r>   r>   r?   r    s    zTestdir.runpythonc             C   s   | j |S )z!See :meth:`Pytester.runpython_c`.)r  r  )rb   r  r>   r>   r?   r    s    zTestdir.runpython_c)r  c            G   s   | j j|d|iS )z*See :meth:`Pytester.runpytest_subprocess`.r  )r  r  )rb   r  r>  r>   r>   r?   r    s    zTestdir.runpytest_subprocess      $@zpexpect.spawn)r  r  r2   c             C   s   | j j||dS )z"See :meth:`Pytester.spawn_pytest`.)r  )r  r  )rb   r  r  r>   r>   r?   r    s    zTestdir.spawn_pytest)r  r  r2   c             C   s   | j j||dS )zSee :meth:`Pytester.spawn`.)r  )r  r  )rb   r  r  r>   r>   r?   r    s    zTestdir.spawnc             C   s   d| j dS )Nz	<Testdir r#  )r  )rb   r>   r>   r?   r     s    zTestdir.__repr__c             C   s
   t | jS )N)rY   r  )rb   r>   r>   r?   __str__  s    zTestdir.__str__)N)N)r  )r>   F)r  )r  )Kr   r   r   r   r  r   r  r  r$   r^   r   r  rN  r  rO  r  r  r   r  setterr%   r  r   r'  r  r  r?  rA  rB  rY   r   rC  rE  r@  rF  rG  r6  rI  rS  r   r   r   r'   r&   r^  ra  r
   rV  rg  rj  rm  rh  r   r  r:   r  r_  rd  r  r  r  r;   r\   r   r   r  rX   r  r  r  r  r  r  r   r  r>   r>   r>   r?   r     sr    

$c               @   s  e Zd ZdZee ddddZedddZeee	e e
f e	e d	d
dZe	e dd	ddZe	e dd	ddZe	e eeegef ddddZee	e dddZddddZeedddZdde	e eddddZdde	e edddd Zdde	e eeegef eedd!d"d#Zedd$d%d&Zedd$d'd(Zeeeegef edd)d*d+Zedd,d-d.Zedd/d0ZdS )1r   zFlexible matching of text.

    This is a convenience class to test large texts like the output of
    commands.

    The constructor takes a list of lines without their trailing newlines, i.e.
    ``text.splitlines()``.
    N)r   r2   c             C   s   || _ g | _d S )N)r   _log_output)rb   r   r>   r>   r?   r     s    zLineMatcher.__init__)r2   c             C   s   d | jS )zReturn the entire original text.

        .. versionadded:: 6.2
            You can use :meth:`str` in older versions.
        rT   )r{   r   )rb   r>   r>   r?   r    s    zLineMatcher.__str__)r}   r2   c             C   s*   t |trt|}t |tr&| j}|S )N)r   rY   r   r8  r   )rb   r}   r>   r>   r?   	_getlines  s
    


zLineMatcher._getlinesc             C   s   d}|  |t dS )zTCheck lines exist in the output in any order (using :func:`python:fnmatch.fnmatch`).TN)_match_lines_randomr   )rb   r}   r   r>   r>   r?   fnmatch_lines_random  s    z LineMatcher.fnmatch_lines_randomc             C   s   d}|  |dd  dS )zMCheck lines exist in the output in any order (using :func:`python:re.match`).Tc             S   s   t t|| S )N)r^   rematch)r   patr>   r>   r?   <lambda>      z3LineMatcher.re_match_lines_random.<locals>.<lambda>N)r  )rb   r}   r   r>   r>   r?   re_match_lines_random  s    z!LineMatcher.re_match_lines_random)r}   
match_funcr2   c             C   sp   d}|  |}x\|D ]T}xN| jD ](}||ks6|||r | dt| P q W d| }| | | | qW d S )NTz	matched: zline %r not found in output)r  r   _logr   _fail)rb   r}   r  r   rN   r   msgr>   r>   r?   r    s    


zLineMatcher._match_lines_random)fnliner2   c             C   sL   x:t | jD ],\}}||ks&t||r| j|d d S qW td| dS )zsReturn all lines following the given line in the text.

        The given line can contain glob wildcards.
        rV   Nzline %r not found in output)r   r   r   r   )rb   r  r   rN   r>   r>   r?   get_lines_after  s    zLineMatcher.get_lines_afterc             G   s    | j ddd |D  d S )Nr  c             s   s   | ]}t |V  qd S )N)rY   )rl   r   r>   r>   r?   rq     s    z#LineMatcher._log.<locals>.<genexpr>)r  ra   r{   )rb   r>  r>   r>   r?   r    s    zLineMatcher._logc             C   s   d | jS )NrT   )r{   r  )rb   r>   r>   r?   	_log_text  s    zLineMatcher._log_textF)consecutive)r}   r  r2   c            C   s   d}| j |td|d dS )a  Check lines exist in the output (using :func:`python:fnmatch.fnmatch`).

        The argument is a list of lines which have to match and can use glob
        wildcards.  If they do not match a pytest.fail() is called.  The
        matches and non-matches are also shown as part of the error message.

        :param lines2: String patterns to match.
        :param consecutive: Match lines consecutively?
        Tr   )r  N)_match_linesr   )rb   r}   r  r   r>   r>   r?   r    s    zLineMatcher.fnmatch_linesc            C   s   d}| j |dd d|d dS )a  Check lines exist in the output (using :func:`python:re.match`).

        The argument is a list of lines which have to match using ``re.match``.
        If they do not match a pytest.fail() is called.

        The matches and non-matches are also shown as part of the error message.

        :param lines2: string patterns to match.
        :param consecutive: match lines consecutively?
        Tc             S   s   t t|| S )N)r^   r  r  )r   r  r>   r>   r?   r  	  r  z,LineMatcher.re_match_lines.<locals>.<lambda>zre.match)r  N)r  )rb   r}   r  r   r>   r>   r?   re_match_lines  s    zLineMatcher.re_match_lines)r}   r  match_nicknamer  r2   c            C   s  t |tjjs"tdt|j| |}| j	dd }g }d}t
|d }d}	x4|D ]*}
d}x|rf|d}|
|kr| dt|
 d}	P n|||
r| d| t|
 | d	jd
|dt| d}	P n|r|	rd|
}| | | d	jd
|dt| | | |s@| d	jd|dt|
 d}| d	jd|dt| || qhW d|
}| | | | qZW g | _dS )aq  Underlying implementation of ``fnmatch_lines`` and ``re_match_lines``.

        :param Sequence[str] lines2:
            List of string patterns to match. The actual format depends on
            ``match_func``.
        :param match_func:
            A callable ``match_func(line, pattern)`` where line is the
            captured line from stdout/stderr and pattern is the matching
            pattern.
        :param str match_nickname:
            The nickname for the match function that will be logged to stdout
            when a match occurs.
        :param consecutive:
            Match lines consecutively?
        zinvalid type for lines2: {}NTrV   Fr   zexact match:z%s:z{:>{width}}zwith:)widthzno consecutive match: znomatch:zand:zremains unmatched: )r   collectionsabcr   	TypeErrorr   rt  r   r  r   rx   r   r  r   r  ra   r  )rb   r}   r  r  r  r|   Z
extralinesr   wnickstartedrN   ZnomatchprintedZnextliner  r>   r>   r?   r    sL    








zLineMatcher._match_lines)r  r2   c             C   s   d}|  |td dS )zEnsure captured lines do not match the given pattern, using ``fnmatch.fnmatch``.

        :param str pat: The pattern to match lines.
        Tr   N)_no_match_liner   )rb   r  r   r>   r>   r?   no_fnmatch_lineQ  s    zLineMatcher.no_fnmatch_linec             C   s   d}|  |dd d dS )zEnsure captured lines do not match the given pattern, using ``re.match``.

        :param str pat: The regular expression to match lines.
        Tc             S   s   t t|| S )N)r^   r  r  )r   r  r>   r>   r?   r  `  r  z.LineMatcher.no_re_match_line.<locals>.<lambda>zre.matchN)r  )rb   r  r   r>   r>   r?   no_re_match_lineY  s    zLineMatcher.no_re_match_line)r  r  r  r2   c       	      C   s   d}d}t |d }x| jD ]}|||rh| d|}| | | djd|dt| | | q|s| djd|dt| d}| djd	|dt| qW g | _d
S )zEnsure captured lines does not have a the given pattern, using ``fnmatch.fnmatch``.

        :param str pat: The pattern to match lines.
        TFrV   z: z{:>{width}}zwith:)r  znomatch:zand:N)rx   r   r  r   r   r  r  )	rb   r  r  r  r   Znomatch_printedr  rN   r  r>   r>   r?   r  c  s    

zLineMatcher._no_match_line)r  r2   c             C   s   d}| j }g | _t| d S )NT)r  r  r(   )rb   r  r   Zlog_textr>   r>   r?   r  z  s    zLineMatcher._failc             C   s   t | S )z Return the entire original text.)rY   )rb   r>   r>   r?   rY     s    zLineMatcher.str)r   r   r   r   r
   rY   r   r  r   r   r   r  r  r  r   r^   r  r  r  r  r  r  r  r  r  r  r  r  r>   r>   r>   r?   r     s0   "
<)qr   collections.abcr  r  rv   rq  rZ   r  r  rP  r;   ru   r{  r   ior   pathlibr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   r   r   weakrefr   attrrN  Z	iniconfigr   r   r   r   Z_pytest._coder   Z_pytest.capturer   Z_pytest.compatr   r   r   r   r   r   r   r   Z_pytest.config.argparsingr    Z_pytest.deprecatedr!   Z_pytest.fixturesr"   r#   Z_pytest.mainr$   Z_pytest.monkeypatchr%   Z_pytest.nodesr&   r'   Z_pytest.outcomesr(   r)   r*   Z_pytest.pathlibr+   Z_pytest.reportsr,   r-   Z_pytest.tmpdirr.   Z_pytest.warning_typesr/   Ztyping_extensionsr0   r  Zpytest_pluginsr`   r@   rI   rD   r   rY   r   r   r   r   r   r   r   r   r   compiler   r   r   r  r   r   r   r   r,  r   r   r>   r>   r>   r?   <module>   s   D
 L	
	

b      T  S