
    i#                        d 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 erddlm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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)	dataclass)total_ordering)TYPE_CHECKING)InvalidVersionVersion)FastMCPComponentc                  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).
    N
str | NonegtelteqT)
match_nonec                   ||S | j                   || 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         j/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/utilities/versions.pymatcheszVersionSpec.matches-   sy     ?77dgg%%(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.intersectN   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)r/   r,   r-   r.   
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)
isinstancer+   NotImplementedr,   r-   r.   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)r7   r+   r8   r,   r-   r.   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())r/   )r   s    r   __repr__zVersionKey.__repr__   s    TYYM++r   N)r   r   r#   None)r    objectr#   r"   )r#   r;   )	r$   r%   r&   r'   	__slots__r5   r9   r<   r?   r)   r   r   r+   r+   q   s"     >I' 4,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.
    )r+   )r   s    r   r   r      s     gr   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   )	components    r   version_sort_keyrF      s    " Y..//r   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_versionsrL      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   rL   rH   rI   s     r   is_version_greaterrP      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   rN   rO   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   rN   rO   s     r   r   r     rR   r   N)r   r   r#   r+   )rE   r	   r#   r+   )rH   r   rI   r   r#   int)rH   r   rI   r   r#   r"   )rH   r   rI   r   r#   r   )r'   
__future__r   dataclassesr   	functoolsr   typingr   packaging.versionr   r   fastmcp.utilities.componentsr	   r   r+   r   rF   rL   rP   r   r   r)   r   r   <module>r[      sy    # ! $   5= R
 R
 R
j F, F, F,R	0(-,
&3"3r   