
    %h8                         d Z ddlZddlZddlZ	 ddlZ	 ddlZdZde dZ	d Z
d Zd Zd	 Zd
 Zd Zd Z G d de      Zy# e$ r dZY 7w xY w# e$ r ddlZY Aw xY w)z
Support for detecting various information from python projects metadata.

Metadata can only be loaded from static files (e.g. pyproject.toml, setup.cfg, etc.)
but not from setup.py due to its dynamic nature.
    Nz(===|==|!=|<=|>=|<|>|~=)z^(z?\d+(\.[\d\*]+)*)+$c                     t        |       D ]  \  }}t        |      }	  ||      }|s|c S  y# t        $ r
}Y d}~1d}~ww xY w)zDetect the python version requirement for a project.

    The directory should contain a metadata file such as pyproject.toml,
    setup.cfg, or .python-version.

    Returns the python version requirement as a string or None if not found.
    N)lookup_metadata_file%get_python_version_requirement_parserInvalidVersionConstraintError)	directory_metadata_fileparserversion_constrainterrs         =/Users/aron/dev/rstudio/rsconnect/inst/resources/pyproject.py!detect_python_version_requirementr      s\     1; 	&=6}E	!'!6
 %%	&  - 		s   /	AAc                 X     t        j                           fd}t         |             S )aM  Given the directory of a project return the path of a usable metadata file.

    The returned value is either a list of tuples [(filename, path)] or
    an empty list [] if no metadata file was found.

    The metadata files are returned in the priority they should be processed
    to determine the python version requirements.
    c               3   T   K   dD ]  } | z  }|j                         s| |f   y w)N).python-versionpyproject.toml	setup.cfg)is_file)filenamepathr   s     r   	_generatez'lookup_metadata_file.<locals>._generate>   s4     J 	'Hx'D||~&&	's   (	()pathlibPathlist)r   r   s   ` r   r   r   2   s'     Y'I' 	    c                     | j                   dk(  rt        S | j                   dk(  rt        S | j                   dk(  rt        S t	        d| j                          )zGiven the metadata file, return the appropriate parser function.

    The returned function takes a pathlib.Path and returns the parsed value.
    r   r   r   zUnknown metadata file type: )nameparse_pyproject_python_requiresparse_setupcfg_python_requiresparse_pyversion_python_requiresNotImplementedError)r	   s    r   r   r   G   s\     --..			{	*--			0	0..!$@ASAS@T"UVVr   c                     | j                         }t        j                  |      }|j                  di       j                  dd      S )zParse the project.requires-python field from a pyproject.toml file.

    Assumes that the pyproject.toml file exists, is accessible and well formatted.

    Returns None if the field is not found.
    projectzrequires-pythonN)	read_texttomllibloadsget)pyproject_filecontent	pyprojects      r   r   r   W   s?     &&(Gg&I==B'++,=tDDr   c                 t    t        j                         }|j                  |        |j                  ddd      S )zParse the options.python_requires field from a setup.cfg file.

    Assumes that the setup.cfg file exists, is accessible and well formatted.

    Returns None if the field is not found.
    optionspython_requiresN)fallback)configparserConfigParserreadr'   )setupcfg_fileconfigs     r   r   r   e   s4     &&(F
KK::i!2T:BBr   c                 P    t        | j                         j                               S )zParse the python version from a .python-version file.

    Assumes that the .python-version file exists, is accessible and well formatted.

    Returns None if the field is not found.
    )adapt_python_requiresr$   strip)pyversion_files    r   r    r    s   s!     !!9!9!;!A!A!CDDr   c                 X    | j                  d      }d }dj                   ||            S )zConvert a literal python version to a PEP440 constraint.

    Connect expects a PEP440 format, but the .python-version file can contain
    plain version numbers and other formats.

    We should convert them to the constraints that connect expects.
    ,c              3     K   | D ]  }|j                         }d|v sd|v sd|v rt        d|       d|v sd|v sd|v rt        d|       t        j                  t        |      t        d	|       t        j
                  t        |      r| d
|v rd|  dj                  |j                  d      d d dgz         }d|   y w)N@-/z3python specific implementations are not supported: brcaz(pre-release versions are not supported: zInvalid python version: *z==.   0z~=)	r6   r   rematchVALID_VERSION_REQ_REGEXsearchPEP440_OPERATORS_REGEXjoinsplit)constraints
constraints     r   _adapt_contraintz/adapt_python_requires.<locals>._adapt_contraint   s     % 	,J#))+Jj C:$5
9J36ijtiu4vwwj DJ$6#:K36^_i^j4kllxx/<D36Nzl4[\\yy/<   *$zl++ "%**:*:3*?*Cse*K!LJzl+++	,s   CC)rK   rJ   )r-   current_contraintsrN   s      r   r5   r5   ~   s2     )..s3,2 88$%7899r   c                       e Zd Zy)r   N)__name__
__module____qualname__ r   r   r   r      s    r   r   )__doc__r/   r   rE   typingImportErrorr%   tomlrI   rG   r   r   r   r   r   r    r5   
ValueErrorr   rT   r   r   <module>rZ      s      	
 5  677JK .*W ECE$:N	J 	o  F
  s"   A A AA	AA