o
    fiD                   
   @   s   d Z ddlZddlmZ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e
eee f d	ee fd
dZG dd deZde
eee f d	ee fddZddededed	ee fddZdS )zUtilities to parse and adjust Python requirements files.

This module parses requirement lines while preserving inline comments and pip arguments and
supports relaxing version pins based on a chosen unfreeze strategy: "none", "major", or "all".

    N)IterableIterator)Path)AnyOptionalUnion)Requirement)Versionstrsreturnc                 c   s>    t | tr
|  } | D ]}| }|r|ds|V  qdS )z{Yield non-empty, non-comment lines from a string or iterable of strings.

    Adapted from pkg_resources.yield_lines.

    #N)
isinstancestr
splitlinesstrip
startswith)r
   line r   f/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/lightning_utilities/install/requirements.py_yield_lines   s   
r   c                       sX   e Zd ZdZdZddddededee d	ed
df
 fddZded
efddZ	  Z
S )_RequirementWithCommenta  Requirement subclass that preserves an inline comment and optional pip argument.

    Attributes:
        comment: The trailing comment captured from the requirement line (including the leading '# ...').
        pip_argument: A preceding pip argument line (e.g., ``"--extra-index-url ..."``) associated
            with this requirement, or ``None`` if not provided.
        strict: Whether the special marker ``"# strict"`` appears in ``comment`` (case-insensitive), in which case
            upper bound adjustments are disabled.

    z# strict Ncommentpip_argumentargsr   r   kwargsr   c                   sL   t  j|i | || _|d u s|std| || _| j| v | _d S )Nzwrong pip argument: )super__init__r   RuntimeErrorr   strict_stringlowerstrict)selfr   r   r   r   	__class__r   r   r   0   s   z _RequirementWithComment.__init__unfreezec                 C   s  t | }| jr| d| j S |dkr<| jD ]#}|jdv r9t|jj}||j |j dt	|d  d  S q|S |dkru| jD ]/}|jdv rr|j |j }|| dd	d| d	}||v rl||d	}|
   S qC|S |d
krtd|d|S )a`  Adjust version specifiers according to the selected unfreeze strategy.

        The special marker ``"# strict"`` in the captured comment disables any relaxation of upper bounds.

        >>> _RequirementWithComment("arrow<=1.2.2,>=1.2.0", comment="# anything").adjust("none")
        'arrow<=1.2.2,>=1.2.0'
        >>> _RequirementWithComment("arrow<=1.2.2,>=1.2.0", comment="# strict").adjust("none")
        'arrow<=1.2.2,>=1.2.0  # strict'
        >>> _RequirementWithComment("arrow<=1.2.2,>=1.2.0", comment="# my name").adjust("all")
        'arrow>=1.2.0'
        >>> _RequirementWithComment("arrow>=1.2.0, <=1.2.2", comment="# strict").adjust("all")
        'arrow<=1.2.2,>=1.2.0  # strict'
        >>> _RequirementWithComment("arrow").adjust("all")
        'arrow'
        >>> _RequirementWithComment("arrow>=1.2.0, <=1.2.2", comment="# cool").adjust("major")
        'arrow<2.0,>=1.2.0'
        >>> _RequirementWithComment("arrow>=1.2.0, <=1.2.2", comment="# strict").adjust("major")
        'arrow<=1.2.2,>=1.2.0  # strict'
        >>> _RequirementWithComment("arrow>=1.2.0").adjust("major")
        'arrow>=1.2.0'
        >>> _RequirementWithComment("arrow").adjust("major")
        'arrow'

        Args:
            unfreeze: One of:
                - ``"none"``: Keep all version specifiers unchanged.
                - ``"major"``: Relax the upper bound to the next major version (e.g., ``<2.0``).
                - ``"all"``: Drop any upper bound constraint entirely.

        Returns:
            The adjusted requirement string. If strict, the original string is returned with the strict marker appended.

        z  major)<z<=r(      z.0all,r   nonezUnexpected unfreeze: z value.)r   r"   r    	specifieroperatorr	   versionr'   replaceintr   
ValueError)r#   r&   outspecr'   upperresultr   r   r   adjust8   s.   "

,

 	z_RequirementWithComment.adjust)__name__
__module____qualname____doc__r    r   r   r   r   r7   __classcell__r   r   r$   r   r   "   s
    .r   c              	   c   s    t | }d}|D ]_}d|v r"|d}|d| ||d }}nd}|drE|dd  }z|t|7 }W n tyD   Y  dS w |drM|}q	|drSq	d|v s]td	|r^q	t	|||d
V  d}q	dS )a  Adapted from ``pkg_resources.parse_requirements`` to include comments and pip arguments.

    Parses a sequence or string of requirement lines, preserving trailing comments and associating any
    preceding pip arguments (``--...``) with the subsequent requirement. Lines starting with ``-r`` or
    containing direct URLs are ignored.

    >>> txt = ['# ignored', '', 'this # is an', '--piparg', 'example', 'foo # strict', 'thing', '-r different/file.txt']
    >>> [r.adjust('none') for r in _parse_requirements(txt)]
    ['this', 'example', 'foo  # strict', 'thing']
    >>> txt = '\\n'.join(txt)
    >>> [r.adjust('none') for r in _parse_requirements(txt)]
    ['this', 'example', 'foo  # strict', 'thing']

    Args:
        strs: Either an iterable of requirement lines or a single multi-line string.

    Yields:
        _RequirementWithComment: Parsed requirement objects with preserved comment and pip argument.

    Nz #r   \z--z-r @z	https?://r   )
r   findendswithr   nextStopIterationr   researchr   )r
   linesr   r   comment_posr   r   r   r   _parse_requirementsq   s2   



rH   base.txtr*   path_dir	file_namer&   c                    s^    dvrt d  dt| | }| s td| ||f | } fddt|D S )aM  Load, parse, and optionally relax requirement specifiers from a file.

    >>> import os
    >>> from lightning_utilities import _PROJECT_ROOT
    >>> path_req = os.path.join(_PROJECT_ROOT, "requirements")
    >>> load_requirements(path_req, "docs.txt", unfreeze="major")  # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
    ['sphinx<6.0,>=4.0', ...]

    Args:
        path_dir: Directory containing the requirements file.
        file_name: The requirements filename inside ``path_dir``.
        unfreeze: Unfreeze strategy: ``"none"``, ``"major"``, or ``"all"`` (see ``_RequirementWithComment.adjust``).

    Returns:
        A list of requirement strings adjusted according to ``unfreeze``.

    Raises:
        ValueError: If ``unfreeze`` is not one of the supported options.
        FileNotFoundError: If the composed path does not exist.

    >   r*   r,   r'   zunsupported option of ""zmissing file for c                    s   g | ]}|  qS r   )r7   ).0reqr&   r   r   
<listcomp>   s    z%load_requirements.<locals>.<listcomp>)r2   r   existsFileNotFoundError	read_textrH   )rJ   rK   r&   pathtextr   rO   r   load_requirements   s   rV   )rI   r*   )r;   rD   collections.abcr   r   pathlibr   typingr   r   r   packaging.requirementsr   packaging.versionr	   r   r   r   rH   listrV   r   r   r   r   <module>   s   ""O$3