
    $j-)                       d Z ddlmZ ddlmZ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mZmZ erddlmZ  ed	e
          Ze G d d                      Ze	 G d d                      Zd%dZd&dZd'dZd(dZd)dZd)dZd*d#Zd$S )+uF  Version comparison utilities for component versioning.

This module provides utilities for comparing component versions. Versions are
strings that are first attempted to be parsed as PEP 440 versions (using the
`packaging` library), falling back to lexicographic string comparison.

Examples:
    - "1", "2", "10" → parsed as PEP 440, compared semantically (1 < 2 < 10)
    - "1.0", "2.0" → parsed as PEP 440
    - "v1.0" → 'v' prefix stripped, parsed as "1.0"
    - "2025-01-15" → not valid PEP 440, compared as strings
    - None → sorts lowest (unversioned components)
    )annotations)CallableSequence)	dataclass)total_ordering)TYPE_CHECKINGAnyTypeVarcast)InvalidVersionVersion)FastMCPComponentC)boundc                  T    e Zd ZU dZdZded<   dZded<   dZded<   ddddZddZ	dS )VersionSpeca  Specification for filtering components by version.

    Used by transforms and providers to filter components to a specific
    version or version range. Unversioned components (version=None) always
    match any spec.

    Args:
        gte: If set, only versions >= this value match.
        lt: If set, only versions < this value match.
        eq: If set, only this exact version matches (gte/lt ignored).
    N
str | NonegtelteqT)
match_noneversionr   boolreturnc                   ||S | j         || j         k    S t          |          }| j        t          | j                  }||k     rdS | j        t          | j                  }||k     sdS dS )a  Check if a version matches this spec.

        Args:
            version: The version to check, or None for unversioned.
            match_none: Whether unversioned (None) components match. Defaults to True
                for backward compatibility with retrieval operations. Set to False
                when filtering (e.g., enable/disable) to exclude unversioned components
                from version-specific rules.

        Returns:
            True if the version matches the spec.
        NFT)r   parse_version_keyr   r   )selfr   r   keygte_keylt_keys         b/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/fastmcp/utilities/versions.pymatcheszVersionSpec.matches0   s     ?7dg%%((8'11GW}}u7&tw//F<<ut    otherVersionSpec | Nonec                X   || S | j         ,|                    | j                   r| S t          d          S |j         ,|                     |j                   r|S t          d          S t          t          | j        |j                  t          | j        |j                            S )a  Return a spec that satisfies both this spec and other.

        Used by transforms to combine caller constraints with filter constraints.
        For example, if a VersionFilter has lt="3.0" and caller requests eq="1.0",
        the intersection validates "1.0" is in range and returns the exact spec.

        Args:
            other: Another spec to intersect with, or None.

        Returns:
            A VersionSpec that matches only versions satisfying both specs.
        N__impossible__)r   )r   r   )r   r"   r   max_versionr   min_versionr   r   r$   s     r!   	intersectzVersionSpec.intersectQ   s     =K7}}TW%% "233338||EH%% "23333 DHei0047EH--
 
 
 	
r#   )r   r   r   r   r   r   )r$   r%   r   r   )
__name__
__module____qualname____doc__r   __annotations__r   r   r"   r+    r#   r!   r   r      s         
 
 CBBAE      B 
  
  
  
  
  
r#   r   c                  6    e Zd ZdZdZddZddZddZddZdS )
VersionKeya:  A comparable version key that handles None, PEP 440 versions, and strings.

    Comparison order:
    1. None (unversioned) sorts lowest
    2. PEP 440 versions sort by semantic version order
    3. Invalid versions (strings) sort lexicographically
    4. When comparing PEP 440 vs string, PEP 440 comes first
    )_is_none
_is_pep440_parsed_rawr   r   r   Nonec                
   || _         |d u | _        d| _        d | _        |b|                    d          r|                    d          n|}	 t          |          | _        d| _        d S # t          $ r || _        Y d S w xY wd S )NFvT)r7   r4   r5   r6   
startswithlstripr   r   )r   r   
normalizeds      r!   __init__zVersionKey.__init__   s    	4-1070B0B30G0GT,,,WJ'&z22"&! ' ' '&' s   A+ +B ?B r$   objectr   c                    t          |t                    st          S | j        r	|j        rdS | j        |j        k    rdS | j        r|j        r| j        |j        k    S | j        s|j        s| j        |j        k    S dS )NTF)
isinstancer3   NotImplementedr4   r5   r6   r*   s     r!   __eq__zVersionKey.__eq__   s    %,, 	"!!= 	U^ 	4=EN**5? 	1u/ 	1<5=00 	1u'7 	1<5=00ur#   c                   t          |t                    st          S | j        r	|j        rdS | j        rdS |j        rdS | j        rO|j        rHt          | j        t                    sJ t          |j        t                    sJ | j        |j        k     S | j        sO|j        sHt          | j        t                    sJ t          |j        t                    sJ | j        |j        k     S | j        S )NFT)rA   r3   rB   r4   r5   r6   r   strr*   s     r!   __lt__zVersionKey.__lt__   s   %,, 	"!!= 	U^ 	5= 	4> 	5 ? 	0u/ 	0dlG44444emW55555<%-// 	0u'7 	0dlC00000emS11111<%-// r#   rE   c                    d| j         dS )NzVersionKey())r7   )r   s    r!   __repr__zVersionKey.__repr__   s    +TY++++r#   N)r   r   r   r8   )r$   r?   r   r   )r   rE   )	r,   r-   r.   r/   	__slots__r>   rC   rF   rI   r1   r#   r!   r3   r3   t   su          >I' ' ' '       4, , , , , ,r#   r3   r   r   r   c                     t          |           S )zParse a version string into a sortable key.

    Args:
        version: The version string, or None for unversioned.

    Returns:
        A VersionKey suitable for sorting.
    )r3   r   s    r!   r   r      s     gr#   	componentr   c                *    t          | j                  S )a  Get a sort key for a component based on its version.

    Use with sorted() or max() to order components by version.

    Args:
        component: The component to get a sort key for.

    Returns:
        A sortable VersionKey.

    Example:
        ```python
        tools = [tool_v1, tool_v2, tool_unversioned]
        highest = max(tools, key=version_sort_key)  # Returns tool_v2
        ```
    )r   r   )rM   s    r!   version_sort_keyrO      s    " Y.///r#   abintc                X    t          |           }t          |          }||k    ||k     z
  S )a  Compare two version strings.

    Args:
        a: First version string (or None).
        b: Second version string (or None).

    Returns:
        -1 if a < b, 0 if a == b, 1 if a > b.

    Example:
        ```python
        compare_versions("1.0", "2.0")  # Returns -1
        compare_versions("2.0", "1.0")  # Returns 1
        compare_versions(None, "1.0")   # Returns -1 (None < any version)
        ```
    )r   )rP   rQ   key_akey_bs       r!   compare_versionsrV      s1    " a  Ea  EEMeem,,r#   r   c                *    t          | |          dk    S )zCheck if version a is greater than version b.

    Args:
        a: First version string (or None).
        b: Second version string (or None).

    Returns:
        True if a > b, False otherwise.
    r   rV   rP   rQ   s     r!   is_version_greaterrZ      s     Aq!!A%%r#   c                B    | |S || S t          | |          dk    r| n|S )zReturn the greater of two versions.

    Args:
        a: First version string (or None).
        b: Second version string (or None).

    Returns:
        The greater version, or None if both are None.
    Nr   rX   rY   s     r!   r(   r(     6     	yy A&&!++112r#   c                B    | |S || S t          | |          dk    r| n|S )zReturn the lesser of two versions.

    Args:
        a: First version string (or None).
        b: Second version string (or None).

    Returns:
        The lesser version, or None if both are None.
    Nr   rX   rY   s     r!   r)   r)     r\   r#   
componentsSequence[C]key_fnCallable[[C], str]list[C]c                   i }| D ]4}|                      ||          g                               |           5g }|                                D ]}t          t          t          |t                              }t          d |D                       rbt          d |D             t          d          }|j
        pi }|                    di |di |                    di           d|iii	          }|                    |           |S )
a  Deduplicate components by key, keeping highest version.

    Groups components by key, selects the highest version from each group,
    and injects available versions into meta if any component is versioned.

    Args:
        components: Sequence of components to deduplicate.
        key_fn: Function to extract the grouping key from a component.

    Returns:
        Deduplicated list with versions injected into meta.
    )r   c              3  (   K   | ]}|j         d uV  d S NrL   .0cs     r!   	<genexpr>z'dedupe_with_versions.<locals>.<genexpr>:  s)      77qy$777777r#   c                *    g | ]}|j         	|j         S re   rL   rf   s     r!   
<listcomp>z(dedupe_with_versions.<locals>.<listcomp><  s!    FFFq	0E0E0E0Er#   T)r   reversemetafastmcpversions)update)
setdefaultappendvaluesr   r   maxrO   anysortedr   rm   
model_copyget)	r^   r`   by_keyrh   resultro   highestall_versionsrm   s	            r!   dedupe_with_versionsr}   #  sZ     "$F 3 3&&))R((//2222FMMOO  !S/?@@@AA77h77777 	!FFHFFF%  L
 <%2D(( ! $"hhy"55$&$ $  ) 
 
G 	gMr#   N)r   r   r   r3   )rM   r   r   r3   )rP   r   rQ   r   r   rR   )rP   r   rQ   r   r   r   )rP   r   rQ   r   r   r   )r^   r_   r`   ra   r   rb   )r/   
__future__r   collections.abcr   r   dataclassesr   	functoolsr   typingr   r	   r
   r   packaging.versionr   r   fastmcp.utilities.componentsr   r   r   r3   r   rO   rV   rZ   r(   r)   r}   r1   r#   r!   <module>r      s    # " " " " " . . . . . . . . ! ! ! ! ! ! $ $ $ $ $ $ 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 >======GCs R
 R
 R
 R
 R
 R
 R
 R
j F, F, F, F, F, F, F, F,R	 	 	 	0 0 0 0(- - - -,
& 
& 
& 
&3 3 3 3"3 3 3 3"* * * * * *r#   