
    $TXg7                    b   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m	Z	 ddl
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZmZ ddl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 m!Z!m"Z" d
dl#m$Z$ d
dl%m&Z& d
dl'm(Z( d
dl)m*Z* d
dl+m,Z, d
dl-m.Z. d
dl/m0Z0 d
dl1m2Z2 d
dl3m4Z4 d
dl5m6Z6 er"ddl7m8Z8m9Z9 ddl:m;Z; ddlm<Z<m=Z=m>Z>m?Z?m@Z@ ddlAmBZB  eeC      ZD ej                  d      d        ZF ej                  d !      d"        ZG ej                  d      d#        ZH ej                  d !      d$        ZI ej                  d !      d%        ZJ ej                         d&        ZK ej                  ej                  j                  d'd(      j                  d)      *      	 	 	 	 	 	 dGd,       ZOej                  	 	 	 	 	 	 dHd-       ZPej                  	 	 	 	 	 	 dId.       ZQ ed/ed0   ed1         ZR	 	 	 	 	 	 	 	 dJd2ZS ej                  d3!      dKd4       ZTe G d5 d6             ZUej                  dLd7       ZV ej                  d3!      dMd8       ZWe G d9 d:             ZXej                  dNd;       ZYe G d< d=             ZZej                  	 	 	 	 	 	 dOd>       Z[ ej                  d3!      	 	 	 	 	 	 dPd?       Z\e G d@ dA             Z]ej                  	 	 	 	 	 	 dQdB       Z^ ej                  d+C      dRdD       Z_ej                  	 	 	 	 	 	 dSdE       Z`ej                  	 	 	 	 	 	 dSdF       Zay)Tz2Collection of pytest fixtures used in conda tests.    )annotationsN)contextmanagernullcontext)	dataclass)	getLogger)Path)copyfile)TYPE_CHECKINGLiteralTypeVaroverload   )EntityEncoder)dals)PACKAGE_CACHE_MAGIC_FILE)conda_tests_ctxt_mgmt_def_polcontextreset_context)main_subshell)YamlRawParameter)env_vars)yaml_round_trip_load)path_to_url)PackageCacheData)
SubdirData)CondaExitZero)TemporaryDirectory)PackageRecord)IterableIterator)MultiCapture)CaptureFixtureExceptionInfoFixtureRequestMonkeyPatchTempPathFactory)MockerFixtureT)autousec                 :    t        j                  dt               y)z
    Suppress `Unclosed Socket Warning`

    It seems urllib3 keeps a socket open to avoid costly recreation costs.

    xref: https://github.com/kennethreitz/requests/issues/1882
    ignore)categoryN)warningsfilterwarningsResourceWarning     6lib/python3.12/site-packages/conda/testing/fixtures.pysuppress_resource_warningr2   5   s     H?r0   function)scopec                    t        t        |             } |j                  | j                         t        j
                  j                  | j                        S )N)dir)r   straddfinalizercleanuppypathlocalname)tmpdirrequests     r1   r>   r>   A   s9    CK0F(77==%%r0   c                 ,    t        j                          y N)r   clear_cached_local_channel_datar/   r0   r1   clear_subdir_cacherC   H   s    ..0r0   c               #     K   t        d      } t        d       dt        j                  dt	        |             i}t        j                  |       d t        d       yw)z
    Fixture that will set "context.number_channel_notices" to 0 and then set
    it back to its original value.

    This is also a good example of how to override values in the context object.
    z+
        number_channel_notices: 0
        r/   testdataN)r   r   r   make_raw_parametersr   r   _set_raw_data)yaml_strrds     r1   disable_channel_noticesrJ   M   s_      	H
 "$88,X6

B
 "	"s   AAc               #  (   K   d t                yw)z:Resets the context object after each test function is run.N)r   r/   r0   r1   reset_conda_contextrL   g   s      
O   c              #     K   | j                  d      }t        dt        |      it              5  | ddd       y# 1 sw Y   yxY ww)zB
    Used to isolate package or index cache from other tests.
    pkgsCONDA_PKGS_DIRS)stack_callbackN)mktempr   r7   r   )tmp_path_factorypkgs_dirs     r1   temp_package_cacherU   o   sE     
  &&v.H		CM*;X
 
 
 
s   .A
>	A
AA
CONDA_TEST_SOLVERSzlibmamba,classic,)paramsmonkeypatchc              #  N   K   t        | || j                        E d{    y7 w)at  
    A parameterized fixture that sets the solver backend to (1) libmamba
    and (2) classic for each test. It's using autouse=True, so only import it in
    modules that actually need it.

    Note that skips and xfails need to be done _inside_ the test body.
    Decorators can't be used because they are evaluated before the
    fixture has done its work!

    So, instead of:

        @pytest.mark.skipif(context.solver == "libmamba", reason="...")
        def test_foo():
            ...

    Do:

        def test_foo():
            if context.solver == "libmamba":
                pytest.skip("...")
            ...
    N)_solver_helperparamr?   rY   s     r1   parametrized_solver_fixturer^   {   s     < g{GMMBBBs   %#%c              #  :   K   t        | |d      E d {    y 7 w)Nclassicr[   r]   s     r1   solver_classicrb      s     
 g{I>>>   c              #  :   K   t        | |d      E d {    y 7 w)Nlibmambara   r]   s     r1   solver_libmambarf      s     
 g{J???rc   Solverre   r`   c              #  ,  K   t         j                  j                  j                          | j	                  t         j                  j                  j                         |j                  d|       t                t         j                  |k(  sJ | y w)NCONDA_SOLVER)r   plugin_managerget_cached_solver_backendcache_clearr8   setenvr   solver)r?   rY   rn   s      r1   r[   r[      sl      44@@B//IIUUV~v.O>>V###
Ls   BBsessionc              #     K   | j                   j                  j                  d      }|j                         5  |j                   d d d        y # 1 sw Y   y xY ww)Ncapturemanager)configpluginmanager	getpluginglobal_and_fixture_disabled_global_capturing)r?   
capmanagers     r1   session_capsysrx      sF      --778HIJ		/	/	1*** 
2	1	1s   6AA	AAAc                  `    e Zd ZU ded<   e	 	 	 	 	 	 dd       Zed	d       Zdd	 	 	 	 	 d
dZy)CondaCLIFixturezCaptureFixture | MultiCapturecapsysc                    y rA   r/   )selfraisesargvs      r1   __call__zCondaCLIFixture.__call__   s    
 *-r0   c                     y rA   r/   )r}   r   s     r1   r   zCondaCLIFixture.__call__   s    QTr0   N)r~   c               J   | j                   j                          t        t        t        |            }d}|rt        j                  |      n	t               5 }t        | }ddd       | j                   j                         \  }}t                |||rfS |fS # 1 sw Y   :xY w)a  Test conda CLI. Mimic what is done in `conda.cli.main.main`.

        `conda ...` == `conda_cli(...)`

        :param argv: Arguments to parse.
        :param raises: Expected exception to intercept. If provided, the raised exception
            will be returned instead of exit code (see pytest.raises and pytest.ExceptionInfo).
        :return: Command results (stdout, stderr, exit code or pytest.ExceptionInfo).
        N)
r{   
readouterrtuplemapr7   pytestr~   r   r   r   )r}   r~   r   code	exceptionouterrs          r1   r   zCondaCLIFixture.__call__   s     	  Sd^$ &,V]]6"+-?9 $'D @ ;;))+S 	Cf66$66 @?s   	BB")r   str | os.PathLike | Pathr~   z-type[Exception] | tuple[type[Exception], ...]returnztuple[str, str, ExceptionInfo])r   r   r   ztuple[str, str, int])r   r   r~   z4type[Exception] | tuple[type[Exception], ...] | Noner   z$tuple[str, str, int | ExceptionInfo])__name__
__module____qualname____annotations__r   r   r/   r0   r1   rz   rz      so    ))-'- >- 
(	- - T T
 HL7'7 E7 
.	7r0   rz   c              #  &   K   t        |        yw)zA function scoped fixture returning CondaCLIFixture instance.

    Use this for any commands that are local to the current test (e.g., creating a
    conda environment only used in the test).
    Nrz   )r{   s    r1   	conda_clir      s      &
!!   c              #  &   K   t        |        yw)zA session scoped fixture returning CondaCLIFixture instance.

    Use this for any commands that are global to the test session (e.g., creating a
    conda environment shared across tests, `conda info`, etc.).
    Nr   )rx   s    r1   session_conda_clir      s      .
))r   c                  6    e Zd ZU ded<   	 	 	 d	 	 	 	 	 	 	 ddZy)PathFactoryFixturer   tmp_pathNc                    |xs d}|xs t        j                         j                  }|xs d}| j                  ||z   |z   z  S )a  Unique, non-existent path factory.

        Extends pytest's `tmp_path` fixture with a new unique, non-existent path for usage in cases
        where we need a temporary path that doesn't exist yet.

        :param name: Path name to append to `tmp_path`
        :param prefix: Prefix to prepend to unique name generated
        :param suffix: Suffix to append to unique name generated
        :return: A new unique path
         )uuiduuid4hexr   )r}   r=   prefixsuffixs       r1   r   zPathFactoryFixture.__call__  sD      2'tzz|''2}} 677r0   )NNN)r=   
str | Noner   r   r   r   r   r   )r   r   r   r   r   r/   r0   r1   r   r   
  s=    N  !!	88 8 	8
 
8r0   r   c              #  &   K   t        |        yw)zA function scoped fixture returning PathFactoryFixture instance.

    Use this to generate any number of temporary paths for the test that are unique and
    do not exist yet.
    N)r   )r   s    r1   path_factoryr   $  s      X
&&r   c                  L    e Zd ZU ded<   ded<   d	dZedd	 	 	 	 	 d
d       Zy)TmpEnvFixturez$PathFactoryFixture | TempPathFactoryr   rz   r   c                    t        | j                  t              r| j                         S | j                  j                  d      S )Nztmp_env-)
isinstancer   r   rR   )r}   s    r1   get_pathzTmpEnvFixture.get_path3  s;    d'');<$$&& $$++J77r0   N)r   c             '     K   t        |xs | j                               } | j                  dd|g|dd  | yw)a   Generate a conda environment with the provided packages.

        :param packages: The packages to install into environment
        :param prefix: The prefix at which to install the conda environment
        :return: The conda environment's prefix
        createz--prefix--yes--quietN)r   r   r   )r}   r   packagess      r1   r   zTmpEnvFixture.__call__;  sC      f/0xVShSSSs   <>)r   r   )r   r7   r   zstr | os.PathLike | Noner   Iterator[Path])r   r   r   r   r   r   r   r/   r0   r1   r   r   .  sH    668  ,0 ) 
	 r0   r   c              #  (   K   t        | |       yw)zA function scoped fixture returning TmpEnvFixture instance.

    Use this when creating a conda environment that is local to the current test.
    Nr   r   r   s     r1   tmp_envr   O  s      i
00rM   c              #  (   K   t        | |       yw)zA session scoped fixture returning TmpEnvFixture instance.

    Use this when creating a conda environment that is shared across tests.
    Nr   )rS   r   s     r1   session_tmp_envr   [  s      (*;
<<rM   c                  4    e Zd ZU ded<   ded<   edd       Zy)TmpChannelFixturer   r   rz   r   c              '    K    | j                   dd| j                          g|ddddt        i t        t	        j
                         j                        }t	        |      }| j                         }|t        j                  z  }|j                  d       |d	z  }|j                  d       i i d
}|D ]t  }|j                  |      D ]^  }	|	d   }
t        ||
z  ||
z         t        di |	j                         j                         D ci c]  \  }}|dvr|| c}}|d   |
<   ` v |dz  j                  t!        j"                  |t$                     |dz  j                  t!        j"                  i t$                     |D ]"  }t'        t	        j(                  |            r"J  |t+        t-        |            f y c c}}w w)Nr   z	--prefix=r   r   z--download-onlyr~   Tparentsnoarch)infor   fn)urlchannelschannelr   zrepodata.json)clsr/   )r   r   r   r   r   first_writablerT   r   subdirmkdirqueryr	   r   dumpitems
write_textjsondumpsr   any	query_allr   r7   )r}   r   rT   
pkgs_cacher   r   r   repodatapackagepkg_datafnamefieldvalues                r1   r   zTmpChannelFixture.__call__l  s     	))+,-	
 	
 		

 	
 	
 !	
 (779BBC%h/
##%7>>)T"8#T"B/G&,,W5 E)6E>:.; / -5MMO,A,A,C,CLE5 (FF u,C/$U+ 6   
/	!--djj}.UV	/	!--djj.OPG'11':;;;   {3w<000s   DGG!BG/"GN)r   r7   r   zIterator[tuple[Path, str]])r   r   r   r   r   r   r/   r0   r1   r   r   g  s     $$*1 *1r0   r   c              #  (   K   t        | |       yw)z?A function scoped fixture returning TmpChannelFixture instance.N)r   r   s     r1   tmp_channelr     s      L)
44rM   )r=   c              #  6  K   |  | j                   D cg c]+  \  }}}|t        j                  u r|j                  d      r|- c}}}x}rCt        j                  ddj                  |              | j                          t        g        yyc c}}}w w)z:A monkeypatch fixture that resets context after each test.CONDA_z+monkeypatch cleanup: undo & reset context: z, N)	_setitemosenviron
startswithlogdebugjoinundor   )rY   objr=   _
conda_varss        r1   context_aware_monkeypatchr     s      
 (000LCq"**!: 	0 z 
 			?		*@U?VWXb s   B0BABc              #  :  K    |        dz  }|j                  d       |t        z  j                          |j                  d|j                  t        |      x}f       t        j                  |fk(  sJ | t        j                  j                  |d       yw)zHA function scoped fixture returning a temporary package cache directory.rO   Tr   z$conda.base.context.Context.pkgs_dirsnew_callablereturn_valueN)r   r   touchpatchPropertyMockr7   r   	pkgs_dirsr   _cache_pop)r   mockerrT   pkgs_dir_strs       r1   tmp_pkgs_dirr     s     
 ~&HNN4N ((//1
LL.((&)(m3l5  
 ///
N  t4s   BBc              #     K    |        dz  }|j                  d       |j                  d|j                  t        |      x}f       t        j
                  |fk(  sJ | yw)zFA function scoped fixture returning a temporary environment directory.envsTr   z$conda.base.context.Context.envs_dirsr   N)r   r   r   r7   r   	envs_dirs)r   r   envs_direnvs_dir_strs       r1   tmp_envs_dirr     sk     
 ~&HNN4N 
LL.((&)(m3l5  
 ///
Ns   A"A$)r?   r$   rY   r%   r   z(Iterable[Literal['libmamba', 'classic']])r?   r$   rY   r%   r   zIterable[Literal['classic']])r?   r$   rY   r%   r   zIterable[Literal['libmamba']])r?   r$   rY   r%   rn   rg   r   zIterable[Solver])r   zIterator[MultiCapture])r{   r"   r   Iterator[CondaCLIFixture])rx   r!   r   r   )r   r   r   zIterator[PathFactoryFixture])r   r   r   rz   r   Iterator[TmpEnvFixture])rS   r&   r   rz   r   r   )r   r   r   rz   r   zIterator[TmpChannelFixture])rY   r%   r   r%   )r   r   r   r'   r   r   )b__doc__
__future__r   r   r   r   r,   
contextlibr   r   dataclassesr   loggingr   pathlibr   shutilr	   typingr
   r   r   r   r:   r   auxlib.entityr   
auxlib.ishr   base.constantsr   base.contextr   r   r   cli.mainr   common.configurationr   	common.ior   common.serializer   
common.urlr   core.package_cache_datar   core.subdir_datar   
exceptionsr   gateways.disk.creater   models.recordsr   collections.abcr   r    _pytest.capturer!   r"   r#   r$   r%   r&   pytest_mockr'   r   r   fixturer2   r>   rC   rJ   rL   rU   r   getsplitr^   rb   rf   rg   r[   rx   rz   r   r   r   r   r   r   r   r   r   r   r   r   r/   r0   r1   <module>r     s9   9 "  	   2 !    < < 	  )  5 P P $ 3   3 $ 6 ) & 5 *2,  *  @ @ j!& "& 1 1 j! "2 j! "   ::>>.0BCII#NCCC .C	C: ??? "? ? @@@ #@ @ 
7:.	0B	C  	  i + !+ +7 +7 +7\ " " i * !* 8 8 82 ' '   @ 1$11 1 1 i =%=&= = != /1 /1 /1d 5$55 !5 5 ]# $  5$5.;55 5( $.; r0   