
    kKj-                       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 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y)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)InvalidVersionVersion)FastMCPComponentC)boundc                  R    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	y)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).
            Matching is PEP 440-normalized and `v`-prefix insensitive, so
            `eq="v1.0"` matches a component versioned `"1.0"`, and `eq="1.0"`
            matches `"1"` (PEP 440 treats `1` and `1.0` as the same version).
            If a server registers two PEP 440-equivalent spellings of the
            same component (e.g. both `"1"` and `"1.0"`), they are the same
            version under this spec; selection among them is deterministic
            (see `version_sort_key`), not registration-order dependent.
    N
str | NonegtelteqT)
match_nonec                  ||S | j                   !t        |      t        | j                         k(  S t        |      }| j                  t        | j                        }||k  ry| j                  t        | j                        }||k  syy)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.
        FT)r   parse_version_keyr   r   )selfversionr   keygte_keylt_keys         k/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/utilities/versions.pymatcheszVersionSpec.matches7   s     ?77$W-1B4771KKK(88'1GW}77&tww/F<    c                p   || S | j                   )|j                  | j                         r| S t        d      S |j                   )| 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.
        __impossible__)r   )r   r   )r   r   r   max_versionr   min_versionr   r   others     r   	intersectzVersionSpec.intersectX   s     =K77}}TWW%"23388||EHH%"233 DHHeii0477EHH-
 	
r    )r   r   r   boolreturnr(   )r&   zVersionSpec | Noner)   r   )
__name__
__module____qualname____doc__r   __annotations__r   r   r   r'    r    r   r   r      s5    & CB
B
AE B 
r    r   c                  4    e Zd ZdZdZddZd	dZd	dZd
dZy)
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_rawc                    || _         |d u | _        d| _        d | _        |=|j	                  d      r|j                  d      n|}	 t        |      | _        d| _        y y # t        $ r
 || _        Y y w xY w)NFvT)r5   r2   r3   r4   
startswithlstripr   r   )r   r   
normalizeds      r   __init__zVersionKey.__init__   sz    	4-1070B0B30G,WJ'&z2"&  " '&'s   A A21A2c                Z   t        |t              st        S | j                  r|j                  ry| j                  |j                  k7  ry| j                  r%|j                  r| j
                  |j
                  k(  S | j                  s%|j                  s| j
                  |j
                  k(  S y)NTF)
isinstancer1   NotImplementedr2   r3   r4   r%   s     r   __eq__zVersionKey.__eq__   s|    %,!!==U^^==ENN*??u//<<5==00u'7'7<<5==00r    c                P   t        |t              st        S | j                  r|j                  ry| j                  ry|j                  ry| j                  r]|j                  rQt        | j
                  t              sJ t        |j
                  t              sJ | j
                  |j
                  k  S | j                  s]|j                  sQt        | j
                  t              sJ t        |j
                  t              sJ | j
                  |j
                  k  S | j                  S )NFT)r=   r1   r>   r2   r3   r4   r   strr%   s     r   __lt__zVersionKey.__lt__   s    %,!!==U^^==>> ??u//dllG444emmW555<<%--//u'7'7dllC000emmS111<<%--// r    c                "    d| j                   dS )NzVersionKey())r5   )r   s    r   __repr__zVersionKey.__repr__   s    TYYM++r    N)r   r   r)   None)r&   objectr)   r(   )r)   rA   )	r*   r+   r,   r-   	__slots__r;   r?   rB   rE   r/   r    r   r1   r1   {   s"     >I' 4,r    r1   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.
    )r1   r   s    r   r   r      s     gr    c                L    t        | j                        | j                  xs dfS )a  Get a sort key for a component based on its version.

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

    The key is a `(VersionKey, raw)` tuple. The `VersionKey` orders by PEP 440
    semantics (or lexicographically for non-PEP 440 strings); the raw version
    string is a deterministic tie-breaker so that two components whose versions
    are PEP 440-equivalent but spelled differently (e.g. `"1"` and `"1.0"`) are
    ordered reproducibly instead of by registration order. The raw tie-breaker
    only affects equivalent-version ties and never the primary version order,
    so range/equality matching (which uses `VersionKey` directly) is unchanged.

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

    Returns:
        A deterministic, sortable `(VersionKey, raw)` tuple.

    Example:
        ```python
        tools = [tool_v1, tool_v2, tool_unversioned]
        highest = max(tools, key=version_sort_key)  # Returns tool_v2
        ```
     )r   r   )	components    r   version_sort_keyrN      s%    2 i//0)2C2C2IrJJr    c                D    t        |       }t        |      }||kD  ||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   )abkey_akey_bs       r   compare_versionsrT      s+    " a Ea EEMeem,,r    c                     t        | |      dkD  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   rT   rP   rQ   s     r   is_version_greaterrX     s     Aq!A%%r    c                8    | |S || S t        | |      dk\  r| S |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.
    r   rV   rW   s     r   r#   r#     1     	yy A&!+122r    c                8    | |S || S t        | |      dk  r| S |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.
    r   rV   rW   s     r   r$   r$   !  rZ   r    c                   i }| D ])  }|j                   ||      g       j                  |       + g }|j                         D ]  }t        |t              }t        d |D              rwt        |D cg c]  }|j                  |j                   c}t        d      }|j                  xs i }|j                  di |di |j                  di       d|iii      }|j                  |        |S c c}w )	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  8   K   | ]  }|j                   d u  y w)NrJ   ).0cs     r   	<genexpr>z'dedupe_with_versions.<locals>.<genexpr>I  s     7hqyy$hs   T)r   reversemetafastmcpversions)update)
setdefaultappendvaluesmaxrN   anysortedr   r   rb   
model_copyget)	
componentskey_fnby_keyr_   resultrd   highestall_versionsrb   s	            r   dedupe_with_versionsrt   2  s     "$F&)R(//2  FMMO'787h77!$,FHq		0EHF%L
 <<%2D(( ! $"hhy"5$&$ ) 
G 	g) $* M# Gs   2C5
C5
N)r   r   r)   r1   )rM   r   r)   ztuple[VersionKey, str])rP   r   rQ   r   r)   int)rP   r   rQ   r   r)   r(   )rP   r   rQ   r   r)   r   )rn   zSequence[C]ro   zCallable[[C], str]r)   zlist[C])r-   
__future__r   collections.abcr   r   dataclassesr   	functoolsr   typingr   r	   r
   packaging.versionr   r   fastmcp.utilities.componentsr   r   r   r1   r   rN   rT   rX   r#   r$   rt   r/   r    r   <module>r}      s    # . ! $ . . 5=Cs Y
 Y
 Y
x F, F, F,R	K8-,
&3"3"*** *r    