
    cKa                         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Zddlm	c m
Z
 ddlm	c mZ ddlmZ ddlmZ ddlmZmZmZmZ  G d de          Zd	 Z ej        d
          Zd Zd Zd Zd Zd Zd Z d Z!dS )z3Environment class representing a conda environment.    )absolute_importN)	is_string)conda_manager)_load_string
_save_file
_YAMLErrorryamlc                      e Zd ZdZ	 	 	 	 	 	 d&dZed             Zed             Zd Zed             Z	ed	             Z
ed
             Zd'dZd'dZed             Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zed             Zd Zd Zd Zed             Zed             Zd(dZd  Z d! Z!d" Z"d)d#Z#d$ Z$d% Z%dS )*EnvSpeczdRepresents a set of required conda packages we could potentially instantiate as a Conda environment. Nc
                    |J |J || _         d| _        d| _        t          |          | _        t          |          | _        t          |          | _        || _        d| _        d| _	        d| _
        || _        || _        |	| _        t          t          j        |                    | _        t          d | j        D                       D ]}||| j        v sJ t#                      }
| j        D ]"}t          j        |          }|
||
|j        <   #|
| _        t-                      }g }| j        D ]U}t          j        |          }|=|                    |j                   |j        |j        |                    |           V|| _        t;          |          | _        t#                      }| j        D ]"}tA          j        |          }|
|||j        <   #|| _!        t-                      }| j"        D ]2}tA          j        |          }||                    |j                   3|| _#        tI          j%                    | _&        dS )az  Construct a package set with the given name and packages.

        Args:
            name (str): name of the package set
            conda_packages (list): list of package specs to pass to conda install
            channels (list): list of channel names
            pip_packages (list): list of pip package specs to pass to pip
            description (str or None): one-sentence-ish summary of what this env is
            inherit_from_name (str or None): name of what we inherit from
            inherit_from (EnvSpec or None): pull in packages and channels from
            lock_set (CondaLockSet): locked packages or None
        Nc                     g | ]	}|j         
S r   )name).0specs     9lib/python3.11/site-packages/anaconda_project/env_spec.py
<listcomp>z$EnvSpec.__init__.<locals>.<listcomp>I   s    DDD49DDD    )'_name_path	_readonlytuple_conda_packages	_channels_pip_packages_description_logical_hash_locked_hash_import_hash_inherit_from_names_inherit_from	_lock_set	conda_apisort_platform_list
_platformsdictconda_packages_for_create
parse_specr   _conda_specs_for_create_by_namesetconda_packagesaddconda_constraintpip_constraintappend_conda_logical_specs_name_setsortedconda_constrained_packagespip_packages_for_createpip_api_pip_specs_for_create_by_namepip_packages_pip_logical_specs_name_setr   new_conda_manager_conda)selfr   r+   channelsr6   descriptioninherit_from_namesinherit_from	platformslock_setconda_specs_by_namer   parsedname_setr2   pip_specs_by_names                   r   __init__zEnvSpec.__init__   s   , "---'''

$^44x"<00'!  #5 )!	 <Y G GHH DD1CDDDEE 	D 	DDC44+C#CCCC"ff2 	8 	8D )$//F 837#FK0/B,55%'"' 	< 	<D)$//F <V[)))* <&:O <.55d;;;-5**01K*L*L' FF0 	6 	6D '--F 615!&+.->*55% 	* 	*D'--F *V[)))+3(#577r   c                     | j         S )zGet name of the package set.

        May be None for the anonymous shared base spec
        (toplevel packages, channels sections).
        )r   r:   s    r   r   zEnvSpec.namer   s     zr   c                 ,    | j         | j        S | j         S )z'Get the description of the environment.)r   r   rG   s    r   r<   zEnvSpec.description{   s       	%:$$r   c                    dd l }|                                }|D ]*}|                    |                    d                     +| j        D ]*}|                    |                    d                     +| j        D ]*}|                    |                    d                     +|D ]*}|                    |                    d                     +|                                }|S )Nr   utf-8)hashlibsha1updateencoder6   r;   	hexdigest)r:   r+   r?   rK   mpcresults           r   _compute_hashzEnvSpec._compute_hash   s    LLNN 	( 	(AHHQXXg&&''''" 	( 	(AHHQXXg&&'''' 	( 	(AHHQXXg&&'''' 	( 	(AHHQXXg&&''''r   c                 h    | j         %|                     | j        | j                  | _         | j         S )zGet a hash of our "logical" requirements.

        (Changing logical requirements could change the lock set
        if we recreate it.)

        Order matters (change in order will count as a change).

        )r   rT   r+   r?   rG   s    r   logical_hashzEnvSpec.logical_hash   s6      	Y!%!3!3D4G!X!XD!!r   c                 `    | j         !|                     | j        d          | _         | j         S )zGet a hash of our locked packages (what we'd pass to conda create).

        This is used to see if we need to reprepare
        environments. Order matters (change in order will count as
        a change).
        Nr   r?   )r   rT   r'   rG   s    r   locked_hashzEnvSpec.locked_hash   s8      	a $ 2 243Q]_ 2 ` `D  r   c                 `    | j         !|                     | j        d          | _         | j         S )zGet a hash of parts of the env spec that can appear in environment.yml.

        This is used to see if we need to re-import the environment.yml, requirements.txt
        or whatever. Those files don't have platform information.
        Nr   rX   )r   rT   r+   rG   s    r   import_hashzEnvSpec.import_hash   s8      	V $ 2 243FRT 2 U UD  r   c                 F    d|z   fd}|                      ||          S )N_c                 $    t          |           S N)getattr)r   private_attrs    r   getterz&EnvSpec._get_inherited.<locals>.getter   s    4...r   key_func)_get_inherited_with_getter)r:   public_attrrd   rb   ra   s       @r   _get_inheritedzEnvSpec._get_inherited   sA    [(	/ 	/ 	/ 	/ 	/ ..v.IIIr   c                     fdg } | g|           |d         | u sJ g }|D ] }|                      ||                     !g }|D ]}t          j        |||          }|S )Nc                 f    | D ],}||vr& |j         |           |                    |           -d S r_   )r!   r/   )specsaccumulatorr   _linearized_ancestorss      r   rl   zAEnvSpec._get_inherited_with_getter.<locals>._linearized_ancestors   sT     - -{* -))$*<kJJJ&&t,,,- -r   rc   )r/   r   _combine_keeping_last_duplicate)	r:   rb   rd   	ancestors
to_combiner   combineditemrl   s	           @r   re   z"EnvSpec._get_inherited_with_getter   s    	- 	- 	- 	- 	- 	tfi000}$$$$
 	, 	,DffTll++++ 	h 	hD$DXt^fgggHHr   c                 B    |                      dt          j                  S )zDGet the conda packages to install in the environment as an iterable.r+   )rg   r   _conda_combine_keyrG   s    r   r+   zEnvSpec.conda_packages   s     ""#3]5UVVVr   c                 ,    |                      d          S )z0Get the channels to install conda packages from.r;   rg   rG   s    r   r;   zEnvSpec.channels   s     "":...r   c                 ,    |                      d          S )z,Get the platforms the environment can be on.r?   rv   rG   s    r   r?   zEnvSpec.platforms   s     "";///r   c                 B    |                      dt          j                  S )zBGet the pip packages to install in the environment as an iterable.r6   )rg   r   _pip_combine_keyrG   s    r   r6   zEnvSpec.pip_packages   s     "">=3QRRRr   c                     | j         S z5Conda package names that we require, as a Python set.)r0   rG   s    r   conda_package_names_setzEnvSpec.conda_package_names_set   s     11r   c                 N    t          | j                                                  S r{   )r*   r)   keysrG   s    r   "conda_package_names_for_create_setz*EnvSpec.conda_package_names_for_create_set   s!     47<<>>???r   c                 *    t          | j                  S )z5List of conda package names with version constraints.)r*   _conda_names_constrainedrG   s    r   #conda_package_names_constrained_setz+EnvSpec.conda_package_names_constrained_set   s     40111r   c                 *    t          | j                  S z3Pip package names that we require, as a Python set.)r*   r7   rG   s    r   pip_package_names_setzEnvSpec.pip_package_names_set   s     43444r   c                 N    t          | j                                                  S r   )r*   r5   r~   rG   s    r    pip_package_names_for_create_setz(EnvSpec.pip_package_names_for_create_set   s!     45::<<===r   c                     | j         S )z'Get ``CondaLockSet`` for this env spec.)r"   rG   s    r   r@   zEnvSpec.lock_set   s     ~r   c                 f    | j         $| j         j        r| j         j        r| j         j        S | j        S )z=Get conda packages (preferring the lock set list if present).)r"   enabledsupports_current_platform"package_specs_for_current_platformr+   rG   s    r   r'   z!EnvSpec.conda_packages_for_create  s:     > 	'$.*@ 	'T^Em 	'>DD&&r   c                     | j         >| j         j        r2| j         j        r&| j         j        s| j        r| j        S | j         j        S | j        S )z;Get pip packages (preferring the lock set list if present).)r"   r   r   pip_package_specsr6   rG   s    r   r3   zEnvSpec.pip_packages_for_create  s\     > 		%$.*@ 		%T^Em 		% >3 88I 8((~77$$r   c                 n    g }|D ]/}|                     |d           }||                    |           0|S r_   )getr/   )r:   namesmappingrj   r   r   s         r   _specs_for_package_namesz EnvSpec._specs_for_package_names  sI     	# 	#D;;tT**D #T"""r   c                 8    |                      || j                  S z>Get the full install specs given an iterable of package names.)r   r)   r:   r   s     r   specs_for_conda_package_namesz%EnvSpec.specs_for_conda_package_names!  s    ,,UD4XYYYr   c                 8    |                      || j                  S r   )r   r5   r   s     r   specs_for_pip_package_namesz#EnvSpec.specs_for_pip_package_names%  s    ,,UD4VWWWr   c                     | j         S )z$Env spec that we inherit stuff from.)r!   rG   s    r   r>   zEnvSpec.inherit_from)  s     !!r   c                     | j         S )z*Env spec names that we inherit stuff from.)r    rG   s    r   r=   zEnvSpec.inherit_from_names.  s     ''r   Fc                     |rd _          j          fd}d }t          j                            dd                              t          j                  }d}|D ]8} ||          }	 ||	          r |r j                            |	          r|	} n9|O|rM|D ]J} ||          }	 ||	          s2 j                            |	          rt          j	        |	           |	} nK|| _         n ||d                    _          j         S )zEThe filesystem path to the default conda env containing our packages.Nc                     | rt           j                            |           nd} t           j                            t           j                            | j                            }|S )Nenvs)ospath
expanduserabspathjoinr   )	base_pathr   project_dirr:   s     r   _prefixzEnvSpec.path.<locals>._prefix>  sN    =FRBG..y999F	wrw||KDI'V'VWWr   c                 |    t           j                            t           j                            | d                    S )N
conda-meta)r   r   isdirr   )
env_prefixs    r   _foundzEnvSpec.path.<locals>._foundC  s&    w}}RW\\*l%K%KLLLr   ANACONDA_PROJECT_ENVS_PATH r   )
r   r   environr   splitpathsepr9   _is_environment_writableshutilrmtree)
r:   r   resetforce_writabler   r   	env_pathsexisting_envbaseprefixs
   ``        r   r   zEnvSpec.path3  st     	 DJ:  	3     
M M M 
'CRHHNNrzZZI  L!   6&>> > T[=a=abh=i=i #)LE   %  D$WT]]F!6&>> dk.R.RSY.Z.Z f---'- 3)

$WYq\22
zr   c                    t          t          j        |j        | j                            }t          t          j        |j        | j                            }t          t          j        |j        | j                            }|r"dgt          t          d |                    z   }|r"dgt          t          d |                    z   }d                    ||z   |z             S )zFA string showing the comparison between this env spec and another one.z  pip:c                     d| z   S Nz    r   xs    r   <lambda>z#EnvSpec.diff_from.<locals>.<lambda>f  s
    vz r   z  channels:c                     d| z   S r   r   r   s    r   r   z#EnvSpec.diff_from.<locals>.<lambda>h  s
    ! r   
)listdifflibndiffr;   r+   r6   mapr   )r:   oldchannels_diff
conda_diffpip_diffs        r   	diff_fromzEnvSpec.diff_from`  s    W]3<GGHH'-(:D<OPPQQ
c&68IJJKK 	N zD-A-A8)L)L$M$MMH 	]*Od37K7K]3[3[.\.\\Myy3h>???r   c                    d dD             }d } |t          j        |j        | j                            }|D ]}||v r|                    |           t	          |          dk    rdS  |t          j        |j        | j                            }t	          |          dk    rdS  |t          j        |j        | j                            }t	          |          dk    rdS dS )a%  Check whether the diff is exclusively removing 'bokeh' or 'notebook'.

        This is used for a hack, because we can auto-add 'bokeh' or 'notebook'
        packages when we anaconda-project init, and that alone shouldn't result
        in being out of sync with the environment.yml.
        c                     g | ]}d |z   S )- r   )r   rs     r   r   z?EnvSpec.diff_only_removes_notebook_or_bokeh.<locals>.<listcomp>r  s    ???AdQh???r   )bokehnotebookc                 >    t          t          d |                     S )Nc                 V    |                      d          p|                      d          S )Nr   z+ )
startswith)lines    r   r   zUEnvSpec.diff_only_removes_notebook_or_bokeh.<locals>.filter_context.<locals>.<lambda>u  s$    DOOD,A,A,ZT__UYEZEZ r   )r   filter)itemss    r   filter_contextzCEnvSpec.diff_only_removes_notebook_or_bokeh.<locals>.filter_contextt  s    ZZ\abbcccr   r   FT)r   r   r+   removelenr;   r6   )r:   r   	to_remover   r   r   r   r   s           r   #diff_only_removes_notebook_or_bokehz+EnvSpec.diff_only_removes_notebook_or_bokehk  s    @?)>???		d 	d 	d $^GM#2DdFY$Z$Z[[
 	% 	%AJ %!!!$$$z??Q 	5&w}S\4='Q'QRR}! 	5!>'-0@$BS"T"TUUx==1 	5tr   c                    t          | j                  }t          | j                  }|r#|                    t	          |                     t          | j                  }t          | j                  }t          j        dt          j	                  }| j
        | j
        |d         d<   n	|d         d= ||d         d<   ||d         d<   t          |          d	k    r||d         d
<   t          | j                  d	k    rEt          | j                  dk    r| j        d	         }nt          | j                  }||d         d<   |d         S )z6Get JSON for an anaconda-project.yml env spec section.pipzCsomething:
    description: null
    packages: []
    channels: []
LoaderN	somethingr<   packagesr;   r   r?      r>   )r   r   r   r/   r&   r   r%   r	   loadRoundTripLoaderr   r   r=   )r:   r   r6   r;   r?   template_jsonr   s          r   to_jsonzEnvSpec.to_json  sf   
 ,--D.// 	4OOD\222333''))	 
#v*/*?A A A  	:8<8IM+&}55k*=919k":.19k":. y>>A 	@6?M+&{3t&''!+ 	?4*++q0 6/2T4559>M+&~6[))r   c                 l   t           j                            |d          }t           j                            |          s"t	          d                    |                    t           j                            |d          }t           j                            |          r=t          |d          5 }|                                }ddd           n# 1 swxY w Y   nd}d                    t          | j
                  t          |          z
            }||k    r|r@t          |dz   d	          5 }|                    |           ddd           n# 1 swxY w Y   t           j                            |          rt          j        ||d
z              |rt          j        |dz   |           dS dS dS )z3Write the augmented pinned file in the environment.r   Expected path {} to existpinnedr   Nr   r   z	.__ap_neww
.__ap_orig)r   r   r   r   RuntimeErrorformatexistsopenreadr*   r2   writerename)r:   r   updatingconda_meta_pathfnamefpold_listnew_lists           r   
apply_pinszEnvSpec.apply_pins  s
   ',,v|<<w}}_-- 	T:AA/RRSSS_h777>>%   	eS!! %R7799% % % % % % % % % % % % % % % H 99S!@AACMMQRRx 	6 '%+-s33 'rHHX&&&' ' ' ' ' ' ' ' ' ' ' ' ' ' 'w~~e$$ 7	%!5666 6	%+-u55555	6 	66 6s$   1CCC2EEEc                    t           j                            |d          }t           j                            |          s"t	          d                    |                    t           j                            |d          }t           j                            |          rRt           j                            |dz             rt          j        |dz   |           dS t          j        |           dS dS )zRemove the pinned file.r   r   r   r   N)	r   r   r   r   r   r   r   r   r   )r:   r   r   r   s       r   remove_pinszEnvSpec.remove_pins  s    ',,v|<<w}}_-- 	T:AA/RRSSS_h777>>%   	!w~~el233 !	%,.66666	%     		! 	!r   c                 b   t          | j                  }t          | j                  }|r#|                    t	          |                     t          | j                  }t          j        dt          j                  }| j	        J | j	        |d<   ||d<   ||d<   t          ||           dS )z Save as an environment.yml file.r   z%name: 
dependencies: []
channels: []
r   Nr   dependenciesr;   )r   r+   r6   r/   r&   r;   r	   r   r   r   r   )r:   filenamer   r6   r;   yamls         r   save_environment_ymlzEnvSpec.save_environment_yml  s     +,,D-.. 	4OOD\222333&&zGPUPefffy$$$yV'^#Z4"""""r   )r   Nr   r   r   Nr_   )FF)r   )&__name__
__module____qualname____doc__rE   propertyr   r<   rT   rV   rY   r[   rg   re   r+   r;   r?   r6   r|   r   r   r   r   r@   r'   r3   r   r   r   r>   r=   r   r   r   r   r   r   r  r   r   r   r   r      s7       nn
 !!$& U8 U8 U8 U8n   X % % X%   " " X" 	! 	! X	! ! ! X!J J J J   & W W XW / / X/ 0 0 X0 S S XS 2 2 X2 @ @ X@ 2 2 X2 5 5 X5 > > X>   X ' ' X' % % X%  Z Z ZX X X " " X" ( ( X(+ + + +Z	@ 	@ 	@  <&* &* &*P6 6 6 6.
! 
! 
!# # # # #r   r   c                 l   	 t          j        | dd          5 }|                                }ddd           n# 1 swxY w Y   t          |          }n# t          t
          f$ r Y dS w xY wd}d|v r|d         }|s1d|v r-|d         r%t          j                            |d                   }|st          j                            |           }|	                    dg           }t          |t                    rt          |          dk    r-|	                    dg           }t          |t                    sg }|	                    d	g           }t          |t                    sg }g }g }|D ]}	t          |	          r|                    |	           't          |	t                    rNd
|	v rJt          |	d
         t                    r/|	d
         D ]&}
t          |
          r|                    |
           'g }|D ]&}t          |          r|                    |           't!          ||||d          S )z=Load an environment.yml as an EnvSpec, or None if not loaded.r   rJ   Nr   r   r   r   r   r;   r   r   )r   r+   r;   r6   r?   )codecsr   r   r   IOErrorr   r   r   basenamer   
isinstancer   r   r   r/   r&   r   )r   filecontentsr   r   raw_dependenciesraw_channelsr+   r6   deppip_depr;   channels                r   _load_environment_ymlr    s   [300 	#Dyy{{H	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#H%%Z    tt D~ F| 4t 	4X 	47##DN33D *w)) xx33&-- "5E1F1F!1K "88J33*D11 	"!88J++LlD)) NL 1 1S>> 	1!!#&&&&T"" 	1u| 	1
3u:t8T8T 	1u: 1 1W%% 1 ''000H % %W 	%OOG$$$^h]iuwxxxxs.   A 9A =A  =A A)(A)z^-([-a-zA-Z0-9]+)\s(.*)c                     	 t          j        | dd          5 }|                                }ddd           n# 1 swxY w Y   n# t          t          f$ r Y dS w xY wg }|D ]}|                                }|                    d          s|dk    r3t                              |          }||	                    d          }|	                    d          }|dk    r|
                    |           |dk    rht          j                            t          j                            |           |          }t          |          }	|	|                    |	j                   |
                    |           t%          d	d
d
|          S )z=Load a requirements.txt as an EnvSpec, or None if not loaded.r   rJ   N#r   r      edefaultr   )r   r+   r;   r6   )r  r   	readlinesr	  r   stripr   _requirement_option_researchgroupr/   r   r   r   dirname_load_requirements_txtextendr6   r   )
r   r  linesr   r   rP   optionpackager   
child_specs
             r   r  r  !  s   [300 	%DNN$$E	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	% 	%Z    tt H " "zz|| ??3 	42: 	"))$// 	"WWQZZFggajjG
 } =((((3 =w||BGOOH$=$=wGG3D99
 =OOJ$;<<<OOD!!!!	"rPXYYYYs.   A 9A =A  =A AAc                 h    |                      d          rt          |           S t          |           S )Nz.txt)endswithr  r  )r   s    r   _load_importabler'  L  s4       /%h///$X...r   c                     d}|D ]9}t           j                            | |          }t          |          }|||fc S :dS )N)zenvironment.ymlzenvironment.yamlzrequirements.txtNN)r   r   r   r'  )directory_path	filenamesr   fullr   s        r   _find_importable_specr-  S  s]    KI $ $w||NH55%% 	$(####	$ <r   c                     t          |          \  }}|dS | D ]%}|j        |j        k    r|j        |j        k    r dS &||fS )Nr)  )r-  r   r[   )project_specsr*  r   r   existings        r   !_find_out_of_sync_importable_specr1  ^  sg    ,^<<T8 |!    =DI% 	 4#33	 <<(r   c                      dgS )Nanacondar   r   r   r   _default_env_spec_packagesr4  m  s
    <r   c           	      x    | d}n| f}t          dt                      g t          j                    dd|          S Nr   r  z-Default environment spec for running commands)r   r+   r;   r?   r<   r=   r>   )r   r4  r#   default_platforms_with_currentshared_base_specr>   s     r   _anaconda_default_env_specr:  q  sS     ,(+	"<">">&EGGN&( ,. . . .r   c           	      `    | d}n| f}t          dg g t          j                    dd|          S r6  )r   r#   r7  r8  s     r   _empty_default_env_specr<    sM     ,(+	"$&EGGN&( ,. . . .r   )"r  
__future__r   r  r   r   r   re#anaconda_project.internal.conda_apiinternalr#   !anaconda_project.internal.pip_apir4   $anaconda_project.internal.py2_compatr   anaconda_projectr   anaconda_project.yaml_filer   r   r   r	   objectr   r  compiler  r  r'  r-  r1  r4  r:  r<  r   r   r   <module>rG     s   : 9 & & & & & &    				 				 7 7 7 7 7 7 7 7 7 3 3 3 3 3 3 3 3 3 : : : : : : * * * * * * R R R R R R R R R R R RK# K# K# K# K#f K# K# K#\4y 4y 4yn $$>?? (Z (Z (ZV/ / /      . . .. . . . .r   