
    Vi8                     4   S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	   SSK
Jr  \R                  S   S:H  r\(       a  SSKJr  OSSKr\rSSKJr  S	 rSS
 jr " S S\5      rS r " S S\5      r " S S\5      rSS jrg! \ a	    SSKJr   Nlf = f)a  Porting notes:

* EchoingStdin.read1() needed to exist for py3 and raw_input
* Not sure why the isolate context manager deals in byte streams and
  then relegates to the Result to do late encoding (in properties no
  less). This is especially troublesome because sys.stdout/stderr
  isn't the same stream as stdout/stderr as returned by the context
  manager. (see the extra flush calls in run's finally block.) Is
  it just for parity with py2? There was a related bug, sys.stdout was
  flushed, but not sys.stderr, which caused py3's error_bytes to come
  through as blank.
* sys.stderr had to be flushed, too, on py3 (in invoke's finally)
* Result.exception was redundant with exc_info
* Result.stderr raised a ValueError when stderr was empty, not just
  when it wasn't captured.
* Instead of isolated_filesystem, I just added chdir to run,
  because pytest already does temporary directories.
* Removed echo_stdin (stdin never echos, as it wouldn't with subprocess)

    N)list2cmdline)partial)	Container   )StringIO)
complementc                     U c  Sn OJ[        U [        5      (       a  U R                  U5      n O#[        U [        5      (       d  [	        SU -  5      e[
        (       a  [        U 5      $ [        R                  " U 5      $ )N    z&expected bytes, text, or None, not: %r)	
isinstanceunicodeencodebytes	TypeErrorPY2r   ioBytesIO)inputencodings     _/home/james-whalen/.local/share/pipx/venvs/semgrep/lib/python3.13/site-packages/face/testing.py_make_input_streamr   2   sc    }	E7	#	#X&u%%@5HII
s::er
   c                    U(       d  [         R                  n[         R                  n[        U 5      n U (       a!  UR	                  U 5        UR                  5         UR                  5       nU(       d  [        eUS   S:X  a  US S nU$ )N
)sysstderrstdinstrwriteflushreadlineEOFError)promptstreamr   lines       r   _fake_getpassr%   >   sh    IIE[FV>>DBx4CRyKr
   c                   h    \ rS rSrSrSS jr\S 5       r\S 5       r\S 5       r	\S 5       r
S	 rS
rg)	RunResultN   aa  Returned from :meth:`CommandChecker.run()`, complete with the
relevant inputs and outputs of the run.

Instances of this object are especially valuable for verifying
expected output via the :attr:`~RunResult.stdout` and
:attr:`~RunResult.stderr` attributes.

API modeled after :class:`subprocess.CompletedProcess` for
familiarity and porting of tests.

Nc                 X    Xl         X l        Xpl        X@l        XPl        X0l        X`l        g N)argsr   checkerstdout_bytesstderr_bytes	exit_codeexc_info)selfr+   r   r/   r-   r.   r0   r,   s           r   __init__RunResult.__init__[   s)    	
((" !r
   c                 F    U R                   (       a  U R                   S   $ S$ )znException instance, if an uncaught error was raised.
Equivalent to ``run_res.exc_info[1]``, but more readable.   N)r0   r1   s    r   	exceptionRunResult.exceptioni   s     $(==t}}Q:d:r
   c                     U R                   $ )zPAlias of :attr:`exit_code`, for parity with :class:`subprocess.CompletedProcess`r/   r6   s    r   
returncodeRunResult.returncodeo   s     ~~r
   c                     U R                   R                  U R                  R                  S5      R	                  SS5      $ )zmThe text output ("stdout") of the command, as a decoded
string. See :attr:`stdout_bytes` for the bytestring.
replace
r   )r-   decoder,   r   r>   r6   s    r   stdoutRunResult.stdoutt   s4    
 !!--y9&	(r
   c                     U R                   c  [        S5      eU R                   R                  U R                  R                  S5      R                  SS5      $ )zThe error output ("stderr") of the command, as a decoded
string. See :attr:`stderr_bytes` for the bytestring. May be
``None`` if *mix_stderr* was set to ``True`` in the
:class:`~face.CommandChecker`.
zstderr not separately capturedr>   r?   r   )r.   
ValueErrorr@   r,   r   r>   r6   s    r   r   RunResult.stderr}   sL     $=>>!!--y9&	(r
   c                    SR                  U R                  5      SR                  U R                  5      /nU R                  (       a  UR	                  SU R
                  < 35        U R                  b  UR	                  SU R                  < 35        U R                  (       a  UR	                  SU R                  < 35        U R                  R                  < SSR                  U5      < S3$ )	Nz	args={!r}zreturncode={!r}zstdout=zstderr=z
exception=(z, ))formatr+   r;   r-   appendrA   r.   r   r7   	__class____name__join)r1   r+   s     r   __repr__RunResult.__repr__   s    ""499-!((9;KKt{{45(KKt{{45>>KK$..:;>>22DIIdODDr
   )r+   r,   r0   r/   r   r.   r-   )NN)rL   
__module____qualname____firstlineno____doc__r2   propertyr7   r;   rA   r   rN   __static_attributes__ r
   r   r'   r'   N   sb    
	! ; ;
   ( ( 
( 
(
Er
   r'   c                     [        U 5      nUS:X  a  [	        U S   5      $ S[        U 5      < 3$ ! [         aP    [        U 5      n [        U5      nS[        U5      S:X  a  US   OU-  s $ ! [         a    [	        U 5      s s $ f = ff = f)Nzany code but %rr5   r   zone of )len	Exceptionr   tuplerepr)	exp_codes	codes_len
comp_codess      r   _get_exp_code_textr_      s    #	N	 A~IaL!! 	*,,  #	*
	#z*J$ZA9M
1S]^^ 	#	?"	##s-   0 B
#A,)B
,BB
BB
c                       \ rS rSrSrS rSrg)
CheckError   zRarely raised directly, :exc:`CheckError` is automatically
raised when a :meth:`CommandChecker.run()` call does not terminate
with an expected error code.

This error attempts to format the stdout, stderr, and stdin of the
run for easier debugging.
c                    Xl         [        U5      nSUR                  < SU< S[        UR                  5      < 3nUR
                  (       a  US-  nXAR
                  -  nUS-  nUR                  (       a  US-  nXAR                  -  nUS-  nUR                  (       a  US-  nXAR                  -  nUS-  n[        R                  X5        g )NzGot exit code z (expected z) when running command: z
stdout = """
z"""
z
stderr = """
z
stdin = """
)resultr_   r/   r   r+   rA   r.   r   r   AssertionErrorr2   )r1   rd   
exit_codesexp_codemsgs        r   r2   CheckError.__init__   s    %j1""Hl6;;.GI==%%C== C7NC%%C== C7NC<<$$C<<C7NC*r
   )rd   N)rL   rP   rQ   rR   rS   r2   rU   rV   r
   r   ra   ra      s    +r
   ra   c                   n   ^  \ rS rSrSrS	S jr\R                  S
S j5       rS r	U 4S jr
SS jrSrU =r$ )CommandChecker   a  Face's main testing interface.

Wrap your :class:`Command` instance in a :class:`CommandChecker`,
:meth:`~CommandChecker.run()` commands with arguments, and get
:class:`RunResult` objects to validate your Command's behavior.

Args:

   cmd: The :class:`Command` instance to test.
   env (dict): An optional base environment to use for subsequent
     calls issued through this checker. Defaults to ``{}``.
   chdir (str): A default path to execute this checker's commands
     in. Great for temporary directories to ensure test isolation.
   mix_stderr (bool): Set to ``True`` to capture stderr into
     stdout. This makes it easier to verify order of standard
     output and errors. If ``True``, this checker's results'
     error_bytes will be set to ``None``. Defaults to ``False``.
   reraise (bool): Reraise uncaught exceptions from within *cmd*'s
     endpoint functions, instead of returning a :class:`RunResult`
     instance. Defaults to ``False``.

c                 b    Xl         U=(       d    0 U l        XPl        X@l        SU l        X0l        g Nutf8)cmdbase_envreraise
mix_stderrr   chdir)r1   rp   envrt   rs   rr   s         r   r2   CommandChecker.__init__   s(    	r$
r
   c              #   *  #    [         R                  " 5       n[        R                  [        R                  [        R
                  pvn[        R                  n[        XR                  5      n	[        U R                  5      n
U=(       d    U R                  nU(       a  U
R                  U5        [        (       a+  [        5       =pU R                  (       a  UnO[        5       =pO[         R"                  " 5       n[         R$                  " XR                  S9n	[         R$                  " XR                  S9nU R                  (       a  UnO3[         R"                  " 5       n[         R$                  " XR                  S9n0 n ['        [         R(                  X5        U(       a  [         R                  " [+        U5      5        XUs[        l        [        l        [        l        [,        [        l        XR                  (       d  WOS 4v   U(       a  [         R                  " U5        ['        [         R(                  U5        UR/                  5         UR/                  5         XVUs[        l        [        l        [        l        U[        l        g ! U(       a  [         R                  " U5        ['        [         R(                  U5        UR/                  5         UR/                  5         XVUs[        l        [        l        [        l        U[        l        f = f7f)N)r   )osgetcwdr   r   rA   r   getpassr   r   dictrq   rt   updater   r   rs   r   r   TextIOWrapper	_sync_envenvironr   r%   r   )r1   r   ru   rt   old_cwd	old_stdin
old_stdout
old_stderrold_getpass	tmp_stdinfull_env
tmp_stdoutbytes_output
tmp_stderrbytes_errorold_envs                   r   _isolateCommandChecker._isolate   s    ))+,/IIszz3::z	oo&umm<	&#OOC 3(0
2J'
+3:5j::<L((]]KI))}}6J'
 jjl----9
 	*bjj(4U$09z-CIsz3:+GOOONN!bjj'* 09z-CIsz3:)GO !bjj'* 09z-CIsz3:)GOs!   E<L?BJ BLBLLc                 p    UR                  S[        [        S/5      5      5        U R                  " U0 UD6$ )zConvenience method around :meth:`~CommandChecker.run()`, with the
same signature, except that this will raise a
:exc:`CheckError` if the command completes with exit code
``0``.
r/   r   )
setdefaultr   setrun)r1   akws      r   failCommandChecker.fail  s1     	k:c1#h#78xx!b!!r
   c                 >  > UR                  S5      (       d  [        [        U ]  U5      $ UR	                  S5      u    p# UR                  S5       Vs/ s H  n[        U5      PM     nn[        U R                  US9$ s  snf ! [         a    [        SU-  5      ef = f)Nfail__z-fail_* shortcuts must end in integers, not %rr:   )
startswithsuperrk   __getattr__	partitionsplitintrY   AttributeErrorr   r   )r1   namer   code_strcscoderK   s         r   r   CommandChecker.__getattr__"  s    w'':4@@01	-&.nnS&9:&9CG&9D: tyyD11	 ; 	- !P#+", - -	-s    B A>(B >B Bc           
         [        U[        [        45      (       a  SR                  U5      nUc  SnO?[        U[        5      (       a  U4nO&[        U[
        5      (       d  [        SU< 35      eUnU R                  X#US9 u  pxSn	Sn[        U[        [        45      (       a  [        R                  " U5      n U R                  R                  U=(       d    S5      n
[        R(                  R+                  5         [        R,                  R+                  5         UR/                  5       nU R0                  (       d  UR/                  5       OSn SSS5        [3        U UUWWUW	S9nU(       a  XV;  a  [5        X5      nUeU$ ! [         a:  n[        R                   " 5       n	UR"                  b  UR"                  OSn SnANSnAf[$         a-    U R&                  (       a  e Sn[        R                   " 5       n	 GNf = f! [        R(                  R+                  5         [        R,                  R+                  5         UR/                  5       nU R0                  (       d  UR/                  5       nf Snf = f! , (       d  f       GN*= f)	a  The :meth:`run` method acts as the primary entrypoint to the
:class:`CommandChecker` instance. Pass arguments as a list or
string, and receive a :class:`RunResult` with which to verify
your command's output.

If the arguments do not result in an expected *exit_code*, a
:exc:`CheckError` will be raised.

Args:

   args: A list or string representing arguments, as one might
      find in :attr:`sys.argv` or at the command line.
   input (str): A string (or list of lines) to be passed to
      the command's stdin. Used for testing
      :func:`~face.prompt` interactions, among others.
   env (dict): A mapping of environment variables to apply on
      top of the :class:`CommandChecker`'s base env vars.
   chdir (str): A string (or stringifiable path) path to
      switch to before running the command. Defaults to
      ``None`` (runs in current directory).
   exit_code (int): An integer or list of integer exit codes
     expected from running the command with *args*. If the
     actual exit code does not match *exit_code*,
     :exc:`CheckError` is raised. Set to ``None`` to disable
     this behavior and always return
     :class:`RunResult`. Defaults to ``0``.

.. note::

   At this time, :meth:`run` interacts with global process
   state, and is not designed for parallel usage.

r   NrV   zaexpected exit_code to be None, int, or Container of ints, representing expected exit_codes, not: )r   ru   rt   r   r   )r,   r+   r   r-   r.   r/   r0   )r   listrZ   rM   r   r   r   r   r   r   shlexr   rp   r   
SystemExitr   r0   r   rY   rr   rA   r   r   getvaluers   r'   ra   )r1   r+   r   ru   rt   r/   rf   rA   r   r0   resser-   r.   run_resexcs                   r   r   CommandChecker.run-  s   D edE]++IIe$EJ	3''#JIy116?B C C #J]]u]=AQ&HI$g//{{4(Rhhll4:2. 

  "

  "%08<v0T+ >. D!%"')5)5&/%-/ )5W1CI1  B<<>')ww':BGG	 *<<	<<>	* 

  "

  "%08<v0T+ >=sP   8I2;$FA/I2
G:0G ;G= 6G:6G=9G::G==A2I//I22
J)rq   rt   rp   r   rs   rr   )NNFF)NNN)NNNr   )rL   rP   rQ   rR   rS   r2   
contextlibcontextmanagerr   r   r   r   rU   __classcell__)rK   s   @r   rk   rk      s>    , 4 4l"	2O Or
   rk   c                 (   [         (       a4  S nUR                  5        VVs0 s H  u  pEU" U5      U" U5      _M     nnnUR                  5        H'  u  pgUb  U R                  U5      X&'   Ub  XpU'   M$   X	 M)     U$ s  snnf ! [         a     M@  f = f)Nc                 R    [        U [        5      (       a  U R                  S5      $ U $ rn   )r   r   r   )xs    r   <lambda>_sync_env.<locals>.<lambda>  s!    z!W/E/E188F+L1Lr
   )r   itemsgetrY   )ru   newbackupr   kvkeyvalues           r   r~   r~     s    
sL03		<vay&)#<iik
''#,FKH	 " M =  		s   A=5B
BB)z
Password: Nr*   ) rS   rx   r   r   rz   r   
subprocessr   	functoolsr   collections.abcr   ImportErrorcollectionsversion_infor   	cStringIOr   r   r   r   boltons.setutilsr   r   r%   objectr'   r_   re   ra   rk   r~   rV   r
   r   <module>r      s   * 
 
    # &) 
qQ"G (	 FE FET-+ +8yV y|}
  &%&s   B BB