U
    42i3                     @  s  d Z ddlm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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dddZ!dddddZ"ddddd Z#G d!d" d"Z$G d#d$ d$Z%G d%d& d&Z&dd'd(d)Z'dd'd*d+Z(d,d-d.d.d/d0d1Z)d-d2d3d4d5Z*d2dd6d7d8Z+dS )9z4Interactive debugging with PDB, the Python Debugger.    )annotationsN)Any)Callable)	Generator)outcomes)ExceptionInfo)CaptureManager)Config)ConftestImportFailure)hookimpl)PytestPluginManager)Parser)
UsageError)Node)
BaseReport)CallInfostrztuple[str, str])valuereturnc              
   C  sP   z|  d\}}W n4 tk
rF } zt| d|W 5 d}~X Y nX ||fS )z#Validate syntax of --pdbcls option.:z) is not in the format 'modname:classname'N)split
ValueErrorargparseArgumentTypeError)r   modname	classnamee r   5/tmp/pip-unpacked-wheel-7n2p7kht/_pytest/debugging.py_validate_usepdb_cls   s    r   r   None)parserr   c                 C  sF   |  d}|jddddd |jddd	td
d |jddddd d S )NZgeneralz--pdbusepdb
store_truezDStart the interactive Python debugger on errors or KeyboardInterrupt)destactionhelpz--pdbcls
usepdb_clszmodulename:classnamez{Specify a custom interactive Python debugger for use with --pdb.For example: --pdbcls=IPython.terminal.debugger:TerminalPdb)r$   metavartyper&   z--tracetracez(Immediately break when running each test)ZgetgroupZ
_addoptionr   )r!   groupr   r   r   pytest_addoption)   s(    
r,   r	   )configr   c                   s   dd l  | dr"| jt d | dr<| jt d tj j	tj
tjf tj	 _	| jt_
| t_dd fdd	}| | d S )
Nr   r*   Zpdbtracer"   Z	pdbinvoker    r   c                     s   t j \ _t _t _d S N)	pytestPDB_savedpop	set_trace_pluginmanager_configr   pdbr   r   finR   s    zpytest_configure.<locals>.fin)r7   getvaluepluginmanagerregisterPdbTrace	PdbInvoker0   r1   appendr3   r4   r5   Zadd_cleanup)r-   r8   r   r6   r   pytest_configureA   s    

r?   c                   @  s   e Zd ZU dZdZded< dZded< g Zded< d	ZdZ	d
ed< e
dddddZe
ddddZe
ddddZe
dd Ze
ddddZdS )r0   z'Pseudo PDB that defers to the real pdb.NzPytestPluginManager | Noner4   zConfig | Noner5   zRlist[tuple[Callable[(Ellipsis, None)], PytestPluginManager | None, Config | None]]r1   r   z"tuple[type[Any], type[Any]] | None_wrapped_pdb_clszCaptureManager | Nonez
str | bool)capmanr   c                 C  s   |r|  S dS )NF)Zis_capturing)clsrA   r   r   r   _is_capturingg   s    zpytestPDB._is_capturing)rA   c              
   C  s  | j sdd l}|jS | j d}| jr>| jd |kr>| jd S |r|\}}zJt| tj| }|d}t	||d }|dd  D ]}	t	||	}qW q t
k
r }
 z(d||f}td|d|
 |
W 5 d }
~
X Y qX ndd l}|j}| ||}||f| _|S )Nr   r'      .r   z--pdbcls: could not import z: )r5   r7   ZPdbr9   r@   
__import__sysmodulesr   getattr	Exceptionjoinr   _get_pdb_wrapper_class)rB   rA   r7   r'   r   r   modpartspdb_clspartexcr   Zwrapped_clsr   r   r   _import_pdb_clsm   s6    



zpytestPDB._import_pdb_clsc                   s$   dd l  G  fddd|}|S )Nr   c                      sl   e Zd ZZdZ fddZ fddZe ZZ fddZ	e	Z
e	Z fdd	Z fd
dZ  ZS )z:pytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapperFc                   s,    j d7  _ t |} j d8  _ |S )NrD   )_recursive_debugsuperdo_debugselfargret	__class__rB   r   r   rU      s    zCpytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapper.do_debugc                   s   t  |}jdkrjd k	s$tjj}|  | j}t	
|}|r|dkrd|dd n|dd| d |d k	st|  n|dd jd k	stjjjj| d d	| _|S )
Nr   global>z#PDB continue (IO-capturing resumed)z'PDB continue (IO-capturing resumed for )zPDB continuer-   r7   T)rT   do_continuerS   r5   AssertionErrorr-   create_terminal_writerline_pytest_capmanr0   rC   sepresumer4   hookZpytest_leave_pdb
_continued)rW   rX   rY   twrA   	capturing)r[   _pytestrB   r   r   r`      s*    



zFpytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapper.do_continuec                   s$   t  |}jdkr td |S )a  Raise Exit outcome when quit command is used in pdb.

                This is a bit of a hack - it would be better if BdbQuit
                could be handled, but this would require to wrap the
                whole pytest run, and adjust the report etc.
                r   Quitting debugger)rT   do_quitrS   r   exitrV   rZ   r   r   rm      s    

zBpytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapper.do_quitc                   s0   t  ||}|s,| jr,| jr,| jjdd |S )zSuspend on setup().

                Needed after do_continue resumed, and entering another
                breakpoint again.
                TZin_)rT   setuprh   rd   suspend_global_capture)rW   ftbrY   r[   r   r   rp      s
    
z@pytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapper.setupc                   sX   t  ||\}}|d krPtdt|d }|rP|| d jddrP|d8 }q,||fS )Nr   rD   Z__tracebackhide__F)rT   	get_stackmaxlenf_localsget)rW   rr   tstackirt   r   r   ru      s    
zDpytestPDB._get_pdb_wrapper_class.<locals>.PytestPdbWrapper.get_stack)__name__
__module____qualname__rd   rh   rU   r`   Zdo_cZdo_contrm   Zdo_qZdo_exitrp   ru   __classcell__r   rk   rA   rB   rt   r   PytestPdbWrapper   s   r   )_pytest.config)rB   rO   rA   r   r   r   r   rL      s    Nz pytestPDB._get_pdb_wrapper_classc           
      O  s  ddl }| jdkrd}n| jd}|r4|jdd | jr|j| j}|  | jdkr|	dd}|dk	r||
d| nZ| |}|dkr|
dd	| d
 n2|r|
dd	| d| d n|
dd	|  | |f |}	| jr| jjj| j|	d |	S )z4Initialize PDB debugging, dropping any IO capturing.r   NcapturemanagerTro   headerr]   r\   zPDB z (IO-capturing turned off)z (IO-capturing turned off for r^   r_   )r   r4   	getpluginZsuspendr5   r-   rb   rc   rS   r2   re   rC   rR   rg   Zpytest_enter_pdb)
rB   methodargskwargsrk   rA   ri   r   rj   _pdbr   r   r   	_init_pdb   s4    


zpytestPDB._init_pdbr    r.   c                 O  s(   t  j}| jd||}|| dS )zBInvoke debugging via ``Pdb.set_trace``, dropping any IO capturing.r3   N)r3   )rG   	_getframef_backr   r3   )rB   r   r   framer   r   r   r   r3     s    
zpytestPDB.set_trace)r}   r~   r   __doc__r4   __annotations__r5   r1   rS   r@   classmethodrC   rR   rL   r   r3   r   r   r   r   r0   \   s"   

&S
&r0   c                   @  s0   e Zd ZdddddddZddd	d
dZdS )r=   r   zCallInfo[Any]r   r    )nodecallreportr   c                 C  sr   |j jd}|rB|jdd | \}}tj| tj| |jd k	sPt	t
|jjtjsnt||j| d S )Nr   Tro   )r-   r:   r   rq   Zread_global_capturerG   stdoutwriteexcinfora   
isinstancer   unittestZSkipTest
_enter_pdb)rW   r   r   r   rA   outerrr   r   r   pytest_exception_interact  s    z#PdbInvoke.pytest_exception_interactExceptionInfo[BaseException]r   r   c                 C  s   t |}t| d S r/   )_postmortem_tracebackpost_mortem)rW   r   rs   r   r   r   pytest_internalerror&  s    zPdbInvoke.pytest_internalerrorN)r}   r~   r   r   r   r   r   r   r   r=     s   r=   c                   @  s$   e Zd ZeddddddZdS )r<   T)wrapperzGenerator[None, object, object]r.   c                 c  s   t | d V S r/   ) wrap_pytest_function_for_tracing)rW   
pyfuncitemr   r   r   pytest_pyfunc_call,  s    zPdbTrace.pytest_pyfunc_callN)r}   r~   r   r   r   r   r   r   r   r<   +  s   r<   r.   c                   s8   t d | jtdd fdd}|| _dS )zChange the Python function object of the given Function item by a
    wrapper which actually enters pdb before calling the python function
    itself, effectively leaving the user in the pdb prompt in the first
    statement of the function.runcallr    r.   c                    s    t jf| |} | d S r/   )	functoolspartialr   )r   r   funcr   Ztestfunctionr   r   r   =  s    z1wrap_pytest_function_for_tracing.<locals>.wrapperN)r0   r   objr   wraps)r   r   r   r   r   r   2  s
    
r   c                 C  s   | j drt|  dS )zaWrap the given pytestfunct item for tracing support if --trace was given in
    the command line.r*   N)r-   r9   r   )r   r   r   r   &maybe_wrap_pytest_function_for_tracingE  s    r   r   r   r   )r   r   repr   c                 C  s   | j jdj}|  | j jj}d|jfd|jfd|j	ffD ]N\}}||dfkr>|r>|
dd|  |dd  d	kr|d d }|| q>|
dd
 || |
dd t|}d|_t| |S )NZterminalreporterr   stderrlogallr]   z	captured 
	tracebackzentering PDBT)r-   r:   r   Z_twrc   optionshowcaptureZ	capstdoutZ	capstderrZcaplogre   Z
toterminalr   Z	_pdbshownr   )r   r   r   ri   r   Zsectionnamecontentrs   r   r   r   r   L  s&    

r   ztypes.TracebackTyper   c                 C  sh   ddl m} t| j|r$| jjd S t| jtrL| jjjd k	sBt| jjjS | j	d k	sZt| j	d S d S )Nr   )UnexpectedException   )
doctestr   r   r   exc_infor
   cause__traceback__ra   Z_excinfo)r   r   r   r   r   r   k  s    
r   )rz   r   c                 C  s2   t d}|  |d |  |jr.td d S )Nr   rl   )r0   r   resetZinteractionZquittingr   rn   )rz   pr   r   r   r   |  s
    
r   ),r   
__future__r   r   r   rG   typestypingr   r   r   r   rk   r   Z_pytest._coder   Z_pytest.capturer   r   r	   r
   r   r   Z_pytest.config.argparsingr   Z_pytest.config.exceptionsr   Z_pytest.nodesr   Z_pytest.reportsr   Z_pytest.runnerr   r   r,   r?   r0   r=   r<   r   r   r   r   r   r   r   r   r   <module>   sB    <