
    wBf                        d 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mZ ddlmZmZmZ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/m0Z0m1Z1m2Z2 	 ddl3m3Z3  ee6      Z7ddiZ8ddgiZ9 ejt                  dejv                  ejx                  z        Z= ejt                  d      Z> edg d      Z? G d de@      ZA G d d       ZB G d! d"eB      ZC G d# d$eB      ZD G d% d&eD      ZE G d' d(      ZFd) ZGd* ZHd+ ZId, ZJd- ZKd. ZLd/ ZMd0 ZN ejt                  d1      ZO ejt                  d2      ZP ejt                  d3      ZQ ejt                  d4      ZR ejt                  d5      ZS ejt                  d6      ZT ejt                  d7      ZU ejt                  d8      ZVd9 ZW G d: d;      ZXd< ZY eY       ZZ eX       Z[d>d=Z\y# e4$ r
 ddl5m3Z3 Y qw xY w)?z'Common Python package format utilities.    N)
namedtuple)ConfigParser)reader)HeaderParser)ENOENT)StringIO)chain)	getLoggername)scandirstrerror)basenamedirnameisdirisfilejoinlexists)normpath   )
CondaError)memoizedproperty   )open)groupby_to_dict)get_major_minor_version#get_python_site_packages_short_pathpyc_pathwin_path_ok)
frozendictgraphvizzpython-graphvizz
    # Text needs to be stripped and all extra spaces replaced by single spaces
    (?P<name>^[A-Z0-9][A-Z0-9._-]*)?
    \s?
    (\[(?P<extras>.*)\])?
    \s?
    (?P<constraints>\(? \s? ([\w\d<>=!~,\s\.\*+-]*) \s? \)? )?
    \s?
z1^[^\t\n\r\f\v]+/site-packages/[^\t\n\r\f\v]+\.py$PySpecr   extrasconstraintsmarkerurlc                       e Zd Zy)MetadataWarningN)__name__
__module____qualname__     ?lib/python3.12/site-packages/conda/common/pkg_formats/python.pyr)   r)   B   s    r.   r)   c                       e Zd ZdZdZdZdZdZed        Z	d Z
d Zd Zedd       Zed	        Zd
 Zed        Zd Zd Zd Zd Zd Zd Zd Zd Zed        Zed        Zed        Zed        Zy)PythonDistributionzJBase object describing a python distribution based on path to anchor file.r-   zentry_points.txtc                    |j                  d      rt        | ||      S d|v rt        | ||      S |j                  d      r-t        | t	        |            }t        |      }t        |||      S d|v r?t        | t	        t        |                  }t        t        |            }t        |||      S d|v r?t        | t	        t        |                  }t        t        |            }t        |||      S t               )N	.egg-link
.dist-info	.egg-info.egg)	endswithPythonEggLinkDistributionPythonInstalledDistributionr   r   r   PythonEggInfoDistributionr   NotImplementedError)prefix_pathanchor_filepython_versionanchor_full_pathsp_references        r/   initzPythonDistribution.initP   s   ,,[+~VV[(.{KXX!!+.#K[1IJ#K0L, .,  K'#KW[=Q1RS#GK$89L, .,  {"#KW[=Q1RS#GK$89L, .,  &''r.   c                     || _         || _        |rt        |      rt        |      | _        n#|rt        |      r|| _        nt        d|z        | j                          t        |      | _	        d| _
        d| _        y )NzPath not found: %sr-   )r@   r?   r   r   _metadata_dir_full_pathr   RuntimeError_check_filesPythonDistributionMetadata	_metadata_provides_file_data_requires_file_data)selfr@   r?   s      r/   __init__zPythonDistribution.__init__k   sy     0,'7 8+23C+DD(%(8"9+;D(36FFGG34DE#% #% r.   c                     | j                   D ]N  }| j                  st        | j                  |      }t        |      r2t	        t
        t        t
              |       y)z@Check the existence of mandatory files for a given distribution.N)MANDATORY_FILESrD   r   r   OSErrorr   r   )rK   fnamefpaths      r/   rF   zPythonDistribution._check_files|   sO    )) 	CE++T995Ae}!&(6*:EBB		Cr.   c                     |r+|j                  d      sJ | j                  ||f       |dd }nd}|rt        |      nd}|||fS )z*Normalizes record data content and format.sha256=   N)
startswithrD   int)rK   pathchecksumsizes       r/   _check_path_dataz#PythonDistribution._check_path_data   s`    &&y1 ,,4 1
  |HH s4ydXt##r.   c                 V   i }| j                  d      D cg c]  }|s|j                          }}|r2|d   j                  d      r|d   j                  d      s
d| dg|z   }|D ]p  }|j                  d      r*|j                  d      r|j                         dd }g ||<   >|j                         sO|   j	                  |j                                r g }g }|j                         D ]  \  }}||k(  r|j                  |       |j                  d      r6|j                  dd      }	|D 
cg c]  }
|
|	z   	 }}
|j                  |       d|j	                  |       d	| d
}	|D 
cg c]  }
|
|	z   	 }}
|j                  |        t        |      |fS c c}w c c}
w c c}
w )N
r   []   :z; z; extra == "")	splitstriprU   r8   appenditemsextendreplace	frozenset)dataglobal_sectionrequireslinelinessectionreqsr$   valuesr&   v
new_valuess               r/   _parse_requires_file_dataz,PythonDistribution._parse_requires_file_data   s    *.**T*:C$dCC%(--c2uQx7H7H7M(*+e3E  	7Ds#c(:**,q,$&!zz|!((6	7 '~~/ 	(OGV.(F###C( !d3289Qa&j9
9J' g&'y2289Qa&j9
9J'	(" &&I D6 : :s   FF3F!.F&c                    i }t               }d |_        	 |j                  } |t        |              |j                         D ]  }t        |j                  |            ||<   ! |S # t        $ r |j                  }Y \w xY w)Nc                     | S Nr-   )xs    r/   <lambda>z=PythonDistribution._parse_entries_file_data.<locals>.<lambda>   s    q r.   )	r   optionxform	read_fileAttributeErrorreadfpr   sectionsdictrf   )rj   entries_dataconfigdo_readro   s        r/   _parse_entries_file_dataz+PythonDistribution._parse_entries_file_data   s     (	$&&G 	( 	@G$(g)>$?L!	@   	$mmG	$s   A' 'A?>A?c                 &   d\  }}| j                   D ]n  }t        | j                  |      }t        |      s%t	        |      5 }|j                         }d d d        | j                        \  }}|| _        || _         ||fS  ||fS # 1 sw Y   5xY w)N)NN)	REQUIRES_FILESr   rD   r   r   readrt   rI   rJ   )rK   rl   r$   rP   rQ   fhrj   s          r/   _load_requires_provides_filez/PythonDistribution._load_requires_provides_file   s     &&(( 		E55u=Ee}%[ %B779D% $(#A#A$#G &+1(+3(		 % %s   BB	c                     d }| j                   r5| j                  D ]&  }t        | j                   |      }t        |      s% |S  |S rw   )rD   MANIFEST_FILESr   r   )rK   manifest_full_pathrP   s      r/   r   z%PythonDistribution.manifest_full_path   sS    !'',, %)$*F*F%N",-!!	 "!r.   c                      j                   }|r҉ j                  }t        |      dz   t        |      dk(  }|rt        t	        |            dz   nd fd}d}t        |      5 }t        ||      } ||      }ddd       D 	ch c]  }	|	d   	 c}	t        t        ct        |d	
      fdfdD        D        }
t        g |d |
D              }|S g S # 1 sw Y   gxY wc c}	w )a  
        Read the list of installed paths from record or source file.

        Example
        -------
        [(u'skdata/__init__.py', u'sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU', 0),
         (u'skdata/diabetes.py', None, None),
         ...
        ]
        /installed-files.txt c                 j   g }g }| D ]  }t        	  |d          }t        |      dk(  rG|dd  \  }}|r+|j                  d      sJ j                  ||f       |dd  }nd }|rt	        |      nd }nd x}}||vsu|d   s{|j                  |       |j                  |||f        t        |      S )Nr   r   r_   rS   rT   )posix_normpathlenrU   rD   rV   re   tuple)
r   seenrecordsrowcleaned_pathrX   rY   path_prependerrK   sp_dirs
          r/   process_csv_rowz5PythonDistribution.get_paths.<locals>.process_csv_row   s    ! GC#1VH^<LSQRVH2U#VL3x1}),QR$##+#6#6y#A  $ < < , (D #A
 (0|H'+H,0s4yd*..4#4/CFL1h'EF%G& W~%r.   ,)	delimiterNr   F)with_dotc              3   *   K   | ]
  }|vr|  y wrw   r-   ).0ff	files_sets     r/   	<genexpr>z/PythonDistribution.get_paths.<locals>.<genexpr>!  s#      ! Y&	 !s   c              3   T   K   | ]  }j                  |      s |       ! y wrw   )match)r   f_py_file_re	_pyc_path	py_ver_mms     r/   r   z/PythonDistribution.get_paths.<locals>.<genexpr>#  s+      01+BSBSTUBVIa+s   ((c              3   &   K   | ]	  }|d d f  y wrw   r-   )r   pfs     r/   r   z/PythonDistribution.get_paths.<locals>.<genexpr>)  s     J"b$-Js   )r   r?   r   r   r   r   
csv_readerr   
PY_FILE_REr   sorted)rK   r   r?   prepend_metadata_dirnamer   csv_delimitercsvfilerecord_readerr   recordmissing_pyc_filesr   r   r   r   r   r   s   `          @@@@@@r/   	get_pathszPythonDistribution.get_paths   s    "44!00N8H3NF+,0EE % (!)'2D*E!F!L!#&0  M() 9W *7m L)-89 299v9I%-z"I{/OI!5>! K'KJ8IJKG N	)9 9 :s   .C*C6*C3c                     | j                   j                         }| j                  r| j                  }|S |s| j                          | j                  }|S rw   )rH   get_dist_requirementsrJ   r   rK   rj   s     r/   r   z(PythonDistribution.get_dist_requirements/  sR    
 ~~335##++D  --/++Dr.   c                 6    | j                   j                         S rw   )rH   get_python_requirementsrK   s    r/   r   z*PythonDistribution.get_python_requirements<  s    ~~5577r.   c                 6    | j                   j                         S rw   )rH   get_external_requirementsr   s    r/   r   z,PythonDistribution.get_external_requirements?  s    ~~7799r.   c                     | j                   j                         }| j                  r| j                  }|S |s| j                          | j                  }|S rw   )rH   get_extra_providesrI   r   r   s     r/   r   z%PythonDistribution.get_extra_providesB  sR     ~~002##++D
 	 --/++Dr.   c                 r  	
 ddj                  | j                  j                  d      dd       z  }d 
| j                         }t	        d |D              }t        d |      }|j                  dd	      D ch c]
  } 
|       }}|j                  d
d	      }d| j                  i	|j                  	
fdt        j                  |j                               D               |D ch c]  }|j                  s 
|       }}|j                  |       t        |      t        |      fS c c}w c c}w )z
        Process metadata fields providing dependency information.

        This includes normalizing fields, and evaluating environment markers.
        zpython %s.*.Nr   c                 |    t        t        | j                              }| j                  r| d| j                   S |S )N )pypi_name_to_conda_namenorm_package_namer   r%   )pyspec
conda_names     r/   pyspec_to_norm_reqzEPythonDistribution.get_conda_dependencies.<locals>.pyspec_to_norm_reqW  sG    01B6;;1OPJ %% ,a 2 234  r.   c              3   2   K   | ]  }t        |        y wrw   )parse_specification)r   reqs     r/   r   z<PythonDistribution.get_conda_dependencies.<locals>.<genexpr>`  s     AS+C0As   c                 \    | j                   j                  dd      d   j                         S )N==r_   r   )r&   rc   rd   )pss    r/   ry   z;PythonDistribution.get_conda_dependencies.<locals>.<lambda>a  s#    299??4+CA+F+L+L+N r.   r   r-   extrar?   c              3   Z   K   | ]"  }t        |j                        r
 |       $ y wrw   )	interpretr&   )r   r   execution_contextr   s     r/   r   z<PythonDistribution.get_conda_dependencies.<locals>.<genexpr>g  s-      
(9: v&
s   (+)r   r?   rc   r   r   groupbypopupdater	   from_iterablerq   r%   addr   )rK   python_specrp   pyspecsmarker_groupsr   dependsr$   
constrainsr   r   s            @@r/   get_conda_dependenciesz)PythonDistribution.get_conda_dependenciesO  s5    $chht/B/B/H/H/Mbq/Q&RR	 ))+ADAA NPWX<I<M<MbRT<UV&%f-VV""7B/d11
 	 
--m.B.B.DE
 	
 6<
+1v?Q?Qv&

 
 	K gz 222 W
s   9D/*D4<
D4c                     t         rw   )r<   r   s    r/   get_optional_dependenciesz,PythonDistribution.get_optional_dependenciess  s    !!r.   c                     | j                   D ]H  }t        | j                  |      }t        |      s%t	        |      5 }|j                         }d d d        J | j                        S # 1 sw Y   exY wrw   )ENTRY_POINTS_FILESr   rD   r   r   r   r   )rK   rP   rQ   r   rj   s        r/   get_entry_pointsz#PythonDistribution.get_entry_pointsv  ss     ,, 	%E55u=Ee}%[ %B779D% %	%
 ,,T22% %s   A))A2	c                 .    | j                   j                  S rw   )rH   r   r   s    r/   r   zPythonDistribution.name  s    ~~"""r.   c                 ,    t        | j                        S rw   )r   r   r   s    r/   	norm_namezPythonDistribution.norm_name  s     ++r.   c                 ,    t        | j                        S rw   )r   r   r   s    r/   r   zPythonDistribution.conda_name  s    &t~~66r.   c                 .    | j                   j                  S rw   )rH   versionr   s    r/   r   zPythonDistribution.version  s    ~~%%%r.   N)
__global__)r*   r+   r,   __doc__r   r   rN   r   staticmethodrB   rL   rF   rZ   rt   r   r   r   r   r   r   r   r   r   r   r   r   propertyr   r   r   r   r-   r.   r/   r1   r1   H   s    TNNO.( (4&"C$ '' ''R    " " "DL8:"3H"3 # # , , 7 7 & &r.   r1   c                   6     e Zd ZdZdZdZdZdZdZ fdZ	 xZ
S )r:   z}
    Python distribution installed via distutils.

    Notes
    -----
      - https://www.python.org/dev/peps/pep-0376/
    )RECORDr-   )METADATATc                     t        |t        t        |                  }t        |   ||       t        t        |            | _        y rw   )r   r   r   superrL   r   rA   )rK   r=   r>   r?   r@   	__class__s        r/   rL   z$PythonInstalledDistribution.__init__  s<    [9M-NO)>:$W[%9:r.   )r*   r+   r,   r   r   r   rN   r   is_manageablerL   __classcell__r   s   @r/   r:   r:     s0     !NN#O M; ;r.   r:   c                   B     e Zd ZdZdZdZdZdZ fdZe	d        Z
 xZS )r;   z
    Python distribution installed via setuptools.

    Notes
    -----
      - http://peak.telecommunity.com/DevCenter/EggFormats
    )r   SOURCESzSOURCES.txt)zrequires.txtzdepends.txtr-   r2   c                 4    t         |   ||       || _        y rw   )r   rL   rA   )rK   r@   r?   rA   r   s       r/   rL   z"PythonEggInfoDistribution.__init__  s    )>:(r.   c                 N    | j                   xr t        | j                         dk(  S )Nr   )r   r   r   s    r/   r   z'PythonEggInfoDistribution.is_manageable  s,     ## K0015JJ	
r.   )r*   r+   r,   r   r   r   rN   r   rL   r   r   r   r   s   @r/   r;   r;     s9     GN4NO.) 
 
r.   r;   c                   "     e Zd ZdZ fdZ xZS )r9   Fc                 D    t        ||      }d }t        | 	  |||       y rw   )get_dist_file_from_egg_linkr   rL   )rK   r=   r>   r?   r@   rA   r   s         r/   rL   z"PythonEggLinkDistribution.__init__  s'    6{KP)><Hr.   )r*   r+   r,   r   rL   r   r   s   @r/   r9   r9     s    MI Ir.   r9   c                       e Zd ZdZdZ ed      Z ed      Zd Ze	d        Z
ed        Zed        Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zed        Zed        Zy)rG   a  
    Object representing the metada of a Python Distribution given by anchor
    file (or directory) path.

    This metadata is extracted from a single file. Python distributions might
    create additional files that complement this metadata information, but
    that is handled at the python distribution level.

    Notes
    -----
      - https://packaging.python.org/specifications/core-metadata/
      - Metadata 2.1: https://www.python.org/dev/peps/pep-0566/
      - Metadata 2.0: https://www.python.org/dev/peps/pep-0426/ (Withdrawn)
      - Metadata 1.2: https://www.python.org/dev/peps/pep-0345/
      - Metadata 1.1: https://www.python.org/dev/peps/pep-0314/
      - Metadata 1.0: https://www.python.org/dev/peps/pep-0241/
    )r   PKG-INFO))zMetadata-Versionmetadata_version)Namer   )Versionr   )Licenselicense))Platformplatform)zSupported-Platformsupported_platform)zRequires-Distrequires_dist)zRequires-Externalrequires_external)zRequires-Pythonrequires_python)zProvides-Extraprovides_extra)Requiresrl   c                 v    | j                  || j                        }|| _        | j                  |      | _        y rw   )_process_path
FILE_NAMES_path_read_metadata_data)rK   rW   metadata_paths      r/   rL   z#PythonDistributionMetadata.__init__  s1    **4A
((7
r.   c                 R    d} rt               r%|D ]  }t         |      }t        |      s|} |S  |S t               r0dg}|r|j                  |       t	         fd|D              sJ  }|S t        j                  dt               |S t        j                  dt               |S )zAFind metadata file inside dist-info folder, or check direct file.Nr6   c              3   @   K   | ]  }j                  |        y wrw   )r8   )r   filenamerW   s     r/   r   z;PythonDistributionMetadata._process_path.<locals>.<genexpr>&  s     Mx4==2Ms   zMetadata path not found)r   r   r   rg   anywarningswarnr)   )rW   metadata_filenamesr  rP   rQ   	filenamess   `     r/   r  z(PythonDistributionMetadata._process_path  s     T{/ E u-Ee}(- %$  (M	%$$%78M9MMMM $ 	 7I  MM3_Er.   c                     i }|rx|j                         D ]e  \  }}|| j                  v r/| j                  |   }||vr|g||<   .||   j                  |       C|| j                  v sR| j                  |   }|||<   g |S )a  
        Convert the RFC-822 headers data into a dictionary.

        `message` is an email.parser.Message instance.

        The canonical method to transform metadata fields into such a data
        structure is as follows:
          - The original key-value format should be read with
            email.parser.HeaderParser
          - All transformed keys should be reduced to lower case. Hyphens
            should be replaced with underscores, but otherwise should retain
            all other characters
          - The transformed value for any field marked with "(Multiple-use")
            should be a single list containing all the original values for the
            given key
          - The Keywords field should be converted to a list by splitting the
            original value on whitespace characters
          - The message body, if present, should be set to the value of the
            description key.
          - The result should be stored as a string-keyed dictionary.
        )rf   MULTIPLE_USE_KEYSre   SINGLE_USE_KEYS)clsmessagenew_datakeyvaluenew_keys         r/   _message_to_dictz+PythonDistributionMetadata._message_to_dict0  s    . %mmo 
.
U#///!33C8Gh.-2G) )007C///!11#6G(-HW%
. r.   c                     i }|r:t        |      r/t               }t        |      5 }|j                  |      }ddd       | j	                  |      S # 1 sw Y   xY w)z<Read the original format which is stored as RFC-822 headers.N)r   r   r   parser#  )r  rQ   rj   parserfps        r/   r  z)PythonDistributionMetadata._read_metadataZ  sZ     VE]!^F e (||B'( ##D))( (s   AAc                     g }| j                   rW|D ]R  }| j                   j                  |g       }|D ]!  }|j                  |j                                # |sH t	        |      S  t	        |      S )ac  
        Helper method to get multiple data values by keys.

        Keys is an iterable including the preferred key in order, to include
        values of key that might have been replaced (deprecated), for example
        keys can be ['requires_dist', 'requires'], where the key 'requires' is
        deprecated and replaced by 'requires_dist'.
        )r  getre   rd   ri   )rK   keysrj   r   raw_datar   s         r/   _get_multiple_dataz-PythonDistributionMetadata._get_multiple_datah  sr     :: ::>>#r2# -CKK		,-  r.   c                 (    | j                  ddg      S )u  
        Changed in version 2.1: The field format specification was relaxed to
        accept the syntax used by popular publishing tools.

        Each entry contains a string naming some other distutils project
        required by this distribution.

        The format of a requirement string contains from one to four parts:
          - A project name, in the same format as the Name: field. The only
            mandatory part.
          - A comma-separated list of ‘extra’ names. These are defined by the
            required project, referring to specific features which may need
            extra dependencies.
          - A version specifier. Tools parsing the format should accept
            optional parentheses around this, but tools generating it should
            not use parentheses.
          - An environment marker after a semicolon. This means that the
            requirement is only needed in the specified conditions.

        This field may be followed by an environment marker after a semicolon.

        Example
        -------
        frozenset(['pkginfo', 'PasteDeploy', 'zope.interface (>3.5.0)',
                   'pywin32 >1.0; sys_platform == "win32"'])

        Return 'Requires' if 'Requires-Dist' is empty.
        r  rl   r,  r   s    r/   r   z0PythonDistributionMetadata.get_dist_requirements}  s    : &&'DEEr.   c                 &    | j                  dg      S )a&  
        New in version 1.2.

        This field specifies the Python version(s) that the distribution is
        guaranteed to be compatible with. Installation tools may look at this
        when picking which version of a project to install.

        The value must be in the format specified in Version specifiers.

        This field may be followed by an environment marker after a semicolon.

        Example
        -------
        frozenset(['>=3', '>2.6,!=3.0.*,!=3.1.*', '~=2.6',
                   '>=3; sys_platform == "win32"'])
        r  r.  r   s    r/   r   z2PythonDistributionMetadata.get_python_requirements  s    " &&(9':;;r.   c                 &    | j                  dg      S )u^  
        Changed in version 2.1: The field format specification was relaxed to
        accept the syntax used by popular publishing tools.

        Each entry contains a string describing some dependency in the system
        that the distribution is to be used. This field is intended to serve
        as a hint to downstream project maintainers, and has no semantics
        which are meaningful to the distutils distribution.

        The format of a requirement string is a name of an external dependency,
        optionally followed by a version declaration within parentheses.

        This field may be followed by an environment marker after a semicolon.

        Because they refer to non-Python software releases, version numbers for
        this field are not required to conform to the format specified in PEP
        440: they should correspond to the version scheme used by the external
        dependency.

        Notice that there’s is no particular rule on the strings to be used!

        Example
        -------
        frozenset(['C', 'libpng (>=1.5)', 'make; sys_platform != "win32"'])
        r  r.  r   s    r/   r   z4PythonDistributionMetadata.get_external_requirements  s    4 &&(;'<==r.   c                 &    | j                  dg      S )aA  
        New in version 2.1.

        A string containing the name of an optional feature. Must be a valid
        Python identifier. May be used to make a dependency conditional on
        hether the optional feature has been requested.

        Example
        -------
        frozenset(['pdf', 'doc', 'test'])
        r	  r.  r   s    r/   r   z-PythonDistributionMetadata.get_extra_provides  s     &&(8'9::r.   c                 (    | j                  ddg      S )u  
        New in version 1.2.

        Changed in version 2.1: The field format specification was relaxed to
        accept the syntax used by popular publishing tools.

        Each entry contains a string naming a Distutils project which is
        contained within this distribution. This field must include the project
        identified in the Name field, followed by the version : Name (Version).

        A distribution may provide additional names, e.g. to indicate that
        multiple projects have been bundled together. For instance, source
        distributions of the ZODB project have historically included the
        transaction project, which is now available as a separate distribution.
        Installing such a source distribution satisfies requirements for both
        ZODB and transaction.

        A distribution may also provide a “virtual” project name, which does
        not correspond to any separately-distributed project: such a name might
        be used to indicate an abstract capability which could be supplied by
        one of multiple projects. E.g., multiple projects might supply RDBMS
        bindings for use by a given ORM: each project might declare that it
        provides ORM-bindings, allowing other projects to depend only on having
        at most one of them installed.

        A version declaration may be supplied and must follow the rules
        described in Version specifiers. The distribution’s version number
        will be implied if none is specified.

        This field may be followed by an environment marker after a semicolon.

        Return `Provides` in case `Provides-Dist` is empty.
        provides_distprovidesr.  r   s    r/   get_dist_providesz,PythonDistributionMetadata.get_dist_provides  s    D &&'DEEr.   c                 (    | j                  ddg      S )uZ  
        New in version 1.2.

        Changed in version 2.1: The field format specification was relaxed to
        accept the syntax used by popular publishing tools.

        Each entry contains a string describing a distutils project’s
        distribution which this distribution renders obsolete, meaning that
        the two projects should not be installed at the same time.

        Version declarations can be supplied. Version numbers must be in the
        format specified in Version specifiers [1].

        The most common use of this field will be in case a project name
        changes, e.g. Gorgon 2.3 gets subsumed into Torqued Python 1.0. When
        you install Torqued Python, the Gorgon distribution should be removed.

        This field may be followed by an environment marker after a semicolon.

        Return `Obsoletes` in case `Obsoletes-Dist` is empty.

        Example
        -------
        frozenset(['Gorgon', "OtherProject (<3.0) ; python_version == '2.7'"])

        Notes
        -----
        - [1] https://packaging.python.org/specifications/version-specifiers/
        obsoletes_dist	obsoletesr.  r   s    r/   get_dist_obsoletez,PythonDistributionMetadata.get_dist_obsolete  s    < &&(8+'FGGr.   c                 &    | j                  dg      S )a  
        Classifiers are described in PEP 301, and the Python Package Index
        publishes a dynamic list of currently defined classifiers.

        This field may be followed by an environment marker after a semicolon.

        Example
        -------
        frozenset(['Development Status :: 4 - Beta',
                   "Environment :: Console (Text Based) ; os_name == "posix"])
        
classifierr.  r   s    r/   get_classifiersz*PythonDistributionMetadata.get_classifiers  s     &&~66r.   c                 8    | j                   j                  d      S )Nr   r  r)  r   s    r/   r   zPythonDistributionMetadata.name+  s    zz~~f%%r.   c                 8    | j                   j                  d      S )Nr   r>  r   s    r/   r   z"PythonDistributionMetadata.version/  s    zz~~i((r.   N)r*   r+   r,   r   r  r    r  r  rL   r   r  classmethodr#  r  r,  r   r   r   r   r5  r9  r<  r   r   r   r-   r.   r/   rG   rG     s    $ *J !	
O* #	
*8
  2 ' 'R * **F><&>8;"FHH@7 & & ) )r.   rG   c                 j    | r0| j                  dd      j                  dd      j                         S dS )Nr   -_r   )rh   lowerr   s    r/   r   r   6  s0    ?C4<<S!))#s399;KKr.   c                 6    | rt         j                  | |       S dS )Nr   )PYPI_TO_CONDAr)  )	pypi_names    r/   r   r   :  s    6?=Y	2GRGr.   c                     | rvdj                  d | j                  d      D              j                         } | j                  d      r| j	                  d      r| dd } dj                  d | D              } | S d} | S )	z=Normalize a version by removing extra spaces and parentheses.r   c              3   <   K   | ]  }|j                           y wrw   rd   r   rr   s     r/   r   z'norm_package_version.<locals>.<genexpr>A  s     A1779As   ()r_   r`   r   c              3   B   K   | ]  }|j                         s|  y wrw   rJ  rK  s     r/   r   z'norm_package_version.<locals>.<genexpr>F  s     :	!:s   )r   rc   rd   rU   r8   )r   s    r/   norm_package_versionrO  >  sx    ((AgmmC.@AAGGIc"w'7'7'<amG'':W:: N Nr.   c                     | j                  |d      }|d   j                         }d}t        |      dk(  r|d   j                         }||fS )zBSplit a spec by separator and return stripped start and end parts.r_   r   r   r   r`   )rsplitrd   r   )specsepparts
spec_startspec_ends        r/   
split_specrW  M  sM    KKQEq!JH
5zQ9??$xr.   c                    | g d}}}dj                  d | j                  d      D              j                         } t        | d      \  } }t        | d      \  } }t        j                  |       }|r|j                  d      }t        |      }|j                  d      }|r0|j                  d      D cg c]  }|s|j                          c}ng }|j                  d	      }dj                  d
 |j                  d      D              j                         }|j                  d      r|j                  d      r|dd }|j                  dd      }t        |||||      S c c}w )a  
    Parse a requirement from a python distribution metadata and return a
    namedtuple with name, extras, constraints, marker and url components.

    This method does not enforce strict specifications but extracts the
    information which is assumed to be *correct*. As such no errors are raised.

    Example
    -------
    PySpec(name='requests', extras=['security'], constraints='>=3.3.0',
           marker='foo >= 2.7 or bar == 1', url=''])
    r   r   c              3   &   K   | ]	  }|s|  y wrw   r-   )r   ps     r/   r   z&parse_specification.<locals>.<genexpr>g  s     4!!A4   ;@r   r$   r   r%   c              3   &   K   | ]	  }|s|  y wrw   r-   )r   cs     r/   r   z&parse_specification.<locals>.<genexpr>|  s     9aq9r[  rL  rM  r_   r`   rB  r   r#   )r   rc   rd   rW  PARTIAL_PYPI_SPEC_PATTERNr   groupr   rU   r8   rh   r"   )rR  r   r$   constr&   r'   res           r/   r   r   W  s@    B%&D 884tzz#44::<D dC(LD& 4%ID# 	"''-Awwv & "@FV\\#%6<!!'')<B &95;;s#399??AC U^^C%8!BKEc3'tFfRUVV =s   3E!;E!c                    t               }t        |       D ]  }|j                  }d}|j                  d      rdj	                  ||d      }n|j                  d      r1t        t        | |            r| d| }n{dj	                  ||d      }ng|j                  d      r*t        t        | |            rAd	j	                  ||d
d      }n,|j                  d      r| d| }n|j                  d      rތ|s|j                  |        |S )z9Get all the anchor files for the site packages directory.Nr5   z{}/{}/{}r   r6   r   r   r7   z{}/{}/{}/{}zEGG-INFOr4   z.pth)	setr   r   r8   formatr   r   r   r   )site_packages_pathsite_packages_dirsite_packages_anchor_filesentryrP   r>   s         r/   get_site_packages_anchor_filesrl    s   !$+, 8

>>,'$++,=uhOK^^K(d-u56!2 31UG<(//0A5*U^^F#T,e45+22%uj* ^^K(./q8K^^F#&**;7588 &%r.   c           	         d}t        |t        |             }	 t        |      5 }|j                         d   j	                         }ddd       t              r#t        d d t        |      D        D              }nd}|rIt        |      dk7  rt        d	| d
|  d| d      t        ||d         }t        |      rt        |d      }|t        t        t!        t              |      |S # 1 sw Y   xY w# t
        $ rS ddlm} t        | |             5 }|j                         d   j	                         }ddd       n# 1 sw Y   nxY wY w xY w)z4Return the egg info file path following an egg link.Nr   )getpreferredencoding)encodingc              3   0   K   | ]  }|d d dk(  r|  yw)iNr6   r-   )r   r   s     r/   r   z.get_dist_file_from_egg_link.<locals>.<genexpr>  s&       
BCyK'  
s   c              3   4   K   | ]  }|j                     y wrw   r   )r   rk  s     r/   r   z.get_dist_file_from_egg_link.<locals>.<genexpr>  s     LLs   r-   r_   z.Expected exactly one `egg-info` directory in 'z', via egg-link 'z'. Instead found: zy.  These are often left over from legacy operations that did not clean up correctly.  Please remove all but one of these.r   )r   r   r   	readlinesrd   UnicodeDecodeErrorlocalern  r   r   r   r   r   r   rO   r   r   )egg_link_filer=   egg_info_full_pathegg_link_pathr   egg_link_contentsrn  egg_info_fnamess           r/   r   r     sr   k-&@AM
:-  	:B !#q 1 7 7 9		:  !  
L9J1KL 
 
 1$@AR@SSderds t##2"3 4//  ""3_Q5GH#$!%&8*!E!fhv.0ABBK	: 	:
  :/-*>*@A 	:R "q 1 7 7 9	: 	: 	::s@   C7 "C+C7 +C40C7 7!E"E:	EE	EEc                 @    d fdfdfd |       S )ac  
    Parse marker string and return a dictionary containing a marker expression.

    The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in
    the expression grammar, or strings. A string contained in quotes is to be
    interpreted as a literal string, and a string not contained in quotes is a
    variable (such as os_name).
    c                    t         j                  |       }|r*|j                         d   }| |j                         d  } || fS | st	        d      | d   }|dvrt	        d| z        dj                  |d      }| dd  } |g}| r| d   |k(  rn| d   |k(  r|j                  |       | dd  } nZt        j                  |       }|st	        d| z        |j                  |j                         d          | |j                         d  } | rdj                  |      }t	        d|z        |j                  |       dj                  |      }| dd  j                         } || fS )	Nr   zunexpected end of input'"zinvalid expression: %sr   r_   zerror in string literal: %szunterminated string: %s)

IDENTIFIERr   groupsendSyntaxErrorrh   re   STRING_CHUNKr   lstrip)	remainingmresultqoqrT  ss          r/   
marker_varz parse_marker.<locals>.marker_var  st   Y'XXZ]F!!%%'),I: y  9 788!A~!":Y"FGGq"%B!!"ICEQ<1$q\R'LL$ )!"I$**95A)*G)*STTLLA/ )!%%') 4I  GGEN!";a"?@@LLOWWU^F!!",,.Iy  r.   c                 t   | rQ| d   dk(  rI | dd  j                               \  }} | d   dk7  rt        d| z        | dd  j                         } || fS  |       \  }} | rRt        j                  |       }|sn:|j	                         d   }| |j                         d  }  |       \  }} |||d}| rR|}|| fS )Nr   rL  r_   rM  zunterminated parenthesis: %soplhsrhs)r  r  	MARKER_OPr   r~  r  )r  r  r  r  r  r  r&   r  s         r/   marker_exprz!parse_marker.<locals>.marker_expr  s    1, &y}';';'= >FI|s"!"@9"LMM!!",,.I y   (	2NCOOI.XXZ]%aeegi0	!+I!6YC8  Fy  r.   c                      |       \  }} | rCt         j                  |       }|s	 || fS | |j                         d  }  |       \  }} d||d}| rC|| fS )Nandr  )ANDr   r  )r  r  r  r  r  s       r/   
marker_andz parse_marker.<locals>.marker_and  ss    $Y/Y		)$A I~ "!%%'),I(3NCs37C  I~r.   c                      |       \  }} | rCt         j                  |       }|s	 || fS | |j                         d  }  |       \  }} d||d}| rC|| fS )Norr  )ORr   r  )r  r  r  r  r  s       r/   r&   zparse_marker.<locals>.marker#  ss    #I.Y#A I~ "!%%'),I'	2NCc#6C  I~r.   r-   )marker_stringr&   r  r  r  s    @@@@r/   parse_markerr    s%    "!H!&		 -  r.   z^([\w\.-]+)\s*z^([\w\.*+-]+)\s*z^(<=?|>=?|={2,3}|[~!]=)\s*z*^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*z^or\b\s*z	^and\b\s*z(\S+)\s*z(([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)c                 6    t        | t              r| sy| d   dv S )NFr   r|  )
isinstancestr)os    r/   _is_literalr  B  s    aQQ45=r.   c                   L    e Zd ZdZd d d d d d d d	 d
 d d d dZd Zy)	Evaluatorz2This class is used to evaluate marker expressions.c                     | |k(  S rw   r-   rx   ys     r/   ry   zEvaluator.<lambda>L  
    16 r.   c                     | |k(  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>M  s
    AF r.   c                     | |k(  xs | |kD  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>N      16?QU r.   c                     | |k7  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>O  r  r.   c                     | |k  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>P  
    !a% r.   c                     | |k(  xs | |k  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>Q  r  r.   c                     | |kD  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>R  r  r.   c                     | |k(  xs | |kD  S rw   r-   r  s     r/   ry   zEvaluator.<lambda>S  r  r.   c                     | xr |S rw   r-   r  s     r/   ry   zEvaluator.<lambda>T  s
    AG! r.   c                     | xs |S rw   r-   r  s     r/   ry   zEvaluator.<lambda>U  s
    16 r.   c                 
    | |v S rw   r-   r  s     r/   ry   zEvaluator.<lambda>V  s
    16 r.   c                 
    | |vS rw   r-   r  s     r/   ry   zEvaluator.<lambda>W  s
    qz r.   )r   z===z~=z!=<z<=>z>=r  r  inznot inc                    t        |t              r'|d   dv r|dd }|S ||vrt        d|z        ||   }|S t        |t              sJ |d   }|| j                  vrt        d|z        |d   }|d	   }t        |d         r"t        |d	         rt        d
| d| d|       | j                  ||      }| j                  ||      } | j                  |   ||      }|S )z
        Evaluate a marker expression returned by the :func:`parse_requirement`
        function in the specified context.
        r   r|  r_   r`   zunknown variable: %sr  zop not implemented: %sr  r  zinvalid comparison: r   )r  r  r  r   
operationsr<   r  evaluate)	rK   exprcontextr  r  elhserhsr  r  s	            r/   r  zEvaluator.evaluateZ  s   
 dC Aw%a$ ! w&%&<t&CDD   dD)))dB()*BR*GHH;D;D4;'KU,D!$8at1TF"KLL--g.C--g.C(T__R(c2Fr.   N)r*   r+   r,   r   r  r  r-   r.   r/   r  r  H  s7    < ""*!**#!!)Jr.   r  c                     d } t        t        d      r; | t        j                  j                        }t        j                  j                  }nd}d}i d|d|dt
        dt        j                         d	t        j                         d
t        j                         dt        j                         dt        j                         dt        j                         ddj                  t        j                         j                  d      dd       dt        j                  dt
        dt        j                         dt        j                         dt        j                         dt        j                  dd}|S )zBReturn the default context dictionary to use when parsing markers.c                     | j                    d| j                   d| j                   }| j                  }|dk7  r||d   t	        | j
                        z   z  }|S )Nr   finalr   )majorminormicroreleaselevelr  serial)infor   kinds      r/   format_full_versionz7get_default_marker_context.<locals>.format_full_version  sW    ZZL$**Qtzzl;  7?tAwT[[!111Gr.   implementation0r   implementation_nameimplementation_versionos_nameplatform_machineplatform_python_implementationplatform_releaseplatform_systemplatform_versionpython_full_versionr?   r   Nr   sys_platformzos.namezplatform.python_implementationzplatform.versionzplatform.machinezsys.platformr   )hasattrsysr  r   r   r  r  machinepython_implementationreleasesystemr?   r   rc   )r  r  r  r  s       r/   get_default_marker_contextr    s    s$%!4S5G5G5O5O!P!0055!$ 2 	!"8 	7	
 	H,,. 	)(*H*H*J 	H,,. 	8??, 	H,,. 	x668 	#((8#:#:#<#B#B3#G#KL 	 	7 	)(*H*H*J  	H,,.!" 	H,,.#$ 	%& 	'F* Mr.   c                    	 t        |       \  }}|r|d   dk7  rt        d|  d|       t        j	                         }|r|j                  |       t        j                  ||      S # t        $ r}t        d|  d|       d}~ww xY w)z
    Interpret a marker and return a result depending on environment.

    :param marker: The marker to interpret.
    :type marker: str
    :param execution_context: The context used for name lookup.
    :type execution_context: mapping
    z#Unable to interpret marker syntax: z: Nr   #z$unexpected trailing data in marker: )r  	Exceptionr  DEFAULT_MARKER_CONTEXTcopyr   	evaluatorr  )r&   r   r  restrd  r  s         r/   r   r     s    O!&)
d Q3@4&QRR$))+G()dG,,  O?xr!MNNOs   A( (	B1BBrw   )]r   r  rer  r  collectionsr   configparserr   csvr   r   email.parserr   errnor   ior   	itertoolsr	   loggingr
   osr   r  r   r   os.pathr   r   r   r   r   r   	posixpathr   r   r   r   auxlib.decoratorsr   compatr   	iteratorsr   r   rW   r   r   r   r   r    ImportError_vendor.frozendictr*   logrF  PYPI_CONDA_DEPScompileVERBOSE
IGNORECASEr`  r   r"   Warningr)   r1   r:   r;   r9   rG   r   r   rO  rW  r   rl  r   r  r}  VERSION_IDENTIFIER
COMPARE_OPr  r  r  	NON_SPACEr  r  r  r  r  r  r   r-   r.   r/   <module>r     s   .  	 
  " % $ %        C C 0  1  2 1%  !
 
 'BJJ JJ  RZZLM
	HP	Q	g 	F& F&R
;"4 ;0
 2 
4I 9 Ia) a)LLH +W\&D+`W!B RZZ)*
RZZ 34 RZZ56
BJJDE	RZZbjjBJJ{#	rzzEF+ +t'T 45 K	-]$  1001s   G5 5HH