
    kKj@E                       d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	m
Z
mZmZ ddlZerddlmZ ddlmZ ddlmZ ddl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mZmZm 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* ddl+m,Z,m-Z-  G d dej\                        Z/ G d dej\                        Z0 G d de*      Zg dZ1ddZ2y)z2Base classes and interfaces for FastMCP resources.    )annotationsN)Callable)TYPE_CHECKING	AnnotatedAnyClassVaroverload)Docket)	ExecutionFunctionResource)AnnotationsIcon)Resource)AnyUrl
ConfigDictFieldUrlConstraintsfield_validatormodel_validator)SkipJsonSchema)Self)FastMCPDeprecationWarning)	AuthCheck)FastMCPComponent)
TaskConfigTaskMetac                  l     e Zd ZU dZded<   dZded<   dZded<   	 	 d	 	 	 	 	 d fd	Z	 	 	 	 dd
Z xZ	S )ResourceContentaf  Wrapper for resource content with optional MIME type and metadata.

    Accepts any value for content - strings and bytes pass through directly,
    other types (dict, list, BaseModel, etc.) are automatically JSON-serialized.

    Example:
        ```python
        from fastmcp.resources import ResourceContent

        # String content
        ResourceContent("plain text")

        # Binary content
        ResourceContent(b"binary data", mime_type="application/octet-stream")

        # Auto-serialized to JSON
        ResourceContent({"key": "value"})
        ResourceContent(["a", "b", "c"])
        ```
    zstr | bytescontentN
str | None	mime_typedict[str, Any] | Nonemetac                    t        |t              r	|}|xs d}nHt        |t              r	|}|xs d}n/t        j                  |t              j                         }|xs d}t        |   |||       y)u  Create ResourceContent with automatic serialization.

        Args:
            content: The content value. str and bytes pass through directly.
                     Other types (dict, list, BaseModel) are JSON-serialized.
            mime_type: Optional MIME type. Defaults based on content type:
                       str → "text/plain", bytes → "application/octet-stream",
                       other → "application/json"
            meta: Optional metadata dictionary.
        
text/plainapplication/octet-stream)fallbackapplication/json)r    r"   r$   N)
isinstancestrbytespydantic_coreto_jsondecodesuper__init__)selfr    r"   r$   normalized_content	__class__s        g/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/resources/base.pyr1   zResourceContent.__init__A   sx      gs#.5!1\I'!(!?%?I "/!6!6w!M!T!T!V!7%7I!3ytT    c                   t        | j                  t              r`t        j                  j                  t        |t              rt        |      n|| j                  | j                  xs d| j                        S t        j                  j                  t        |t              rt        |      n|t        j                  | j                        j                         | j                  xs d| j                        S )zConvert to MCP resource contents type.

        Args:
            uri: The URI of the resource (required by MCP types)

        Returns:
            TextResourceContents for str content, BlobResourceContents for bytes
        r&   )uritextmimeType_metar'   )r8   blobr:   r;   )r*   r    r+   mcptypesTextResourceContentsr   r"   r$   BlobResourceContentsbase64	b64encoder/   )r2   r8   s     r5   to_mcp_resource_contentsz(ResourceContent.to_mcp_resource_contents^   s     dllC(9911#-c3#7F3KS\\7<ii	 2   9911#-c3#7F3KS%%dll3::<E+Eii	 2  r6   )NN)r    r   r"   r!   r$   r#   )r8   AnyUrl | strreturnz?mcp.types.TextResourceContents | mcp.types.BlobResourceContents)
__name__
__module____qualname____doc____annotations__r"   r$   r1   rC   __classcell__r4   s   @r5   r   r   '   sg    *  Iz "&D
&
 !%&*	UU U $	U:	Hr6   r   c                  j     e Zd ZU dZded<   dZded<   	 d
	 	 	 d fdZe	 	 	 	 dd       Zdd	Z	 xZ
S )ResourceResulta  Canonical result type for resource reads.

    Provides explicit control over resource responses: multiple content items,
    per-item MIME types, and metadata at both the item and result level.

    Accepts:
        - str: Wrapped as single ResourceContent (text/plain)
        - bytes: Wrapped as single ResourceContent (application/octet-stream)
        - list[ResourceContent]: Used directly for multiple items or custom MIME types

    Example:
        ```python
        from fastmcp import FastMCP
        from fastmcp.resources import ResourceResult, ResourceContent

        mcp = FastMCP()

        # Simple string content
        @mcp.resource("data://simple")
        def get_simple() -> ResourceResult:
            return ResourceResult("hello world")

        # Multiple items with custom MIME types
        @mcp.resource("data://items")
        def get_items() -> ResourceResult:
            return ResourceResult(
                contents=[
                    ResourceContent({"key": "value"}),  # auto-serialized to JSON
                    ResourceContent(b"binary data"),
                ],
                meta={"count": 2}
            )
        ```
    list[ResourceContent]contentsNr#   r$   c                J    | j                  |      }t        | 	  ||       y)zCreate ResourceResult.

        Args:
            contents: String, bytes, or list of ResourceContent objects.
            meta: Optional metadata about the resource result.
        )rP   r$   N)_normalize_contentsr0   r1   )r2   rP   r$   
normalizedr4   s       r5   r1   zResourceResult.__init__   s'     --h7
*48r6   c           
        t        | t              rt        |       gS t        | t              rt        |       gS t        | t              rMt        |       D ]=  \  }}t        |t              rt        d| dt        |      j                   d|d       | S t        | t        t        z  t        z  t        z  t        z  t        z        s| !t        t        j                  |       d      gS t        dt        |       j                         )z)Normalize input to list[ResourceContent].z	contents[z] must be ResourceContent, got z. Use ResourceContent(z) to wrap the value.r)   )r"   z;contents must be str, bytes, or list[ResourceContent], got )r*   r+   r   r,   list	enumerate	TypeErrortyperF   dicttupleintfloatbooljsondumps)rP   iitems      r5   rR   z"ResourceResult._normalize_contents   s   
 h$#H-..h&#H-..h%$X.4!$8##A3&Ed4jFYFYEZ [//3h6JL  / O xu!4s!:U!BT!IJ#DJJx$8DVWXXI$x.JaJaIbc
 	
r6   c                    | j                   D cg c]  }|j                  |       }}t        j                  j	                  || j
                        S c c}w )zConvert to MCP ReadResourceResult.

        Args:
            uri: The URI of the resource (required by MCP types)

        Returns:
            MCP ReadResourceResult with converted contents
        )rP   r;   )rP   rC   r=   r>   ReadResourceResultr$   )r2   r8   ra   mcp_contentss       r5   to_mcp_resultzResourceResult.to_mcp_result   sU     HL}}U}t55c:}Uyy++!)) , 
 	
 Vs   AN)rP   #str | bytes | list[ResourceContent]r$   r#   )rP   rg   rE   rO   )r8   rD   rE   zmcp.types.ReadResourceResult)rF   rG   rH   rI   rJ   r$   r1   staticmethodrR   re   rK   rL   s   @r5   rN   rN   y   sa    !F $#"&D
&
 '+959 $9 
5
	
 
6
r6   rN   c                  
    e Zd ZU dZdZded<    ed      Z edd	      Z	d
ed<    edd	      Z
ded<    edd	      Zded<   dZded<   dZded<   edddddddddddd	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d+d       Z edd      ed,d              Z ed      d-d       Z	 	 d.dZd/d Zed0d1d!       Zed2d"       Z	 d0	 	 	 d3d#Z	 	 	 	 d4d$Zd5d%Zed5d&       Zd6d'Zddd(	 	 	 	 	 	 	 	 	 d7d)Zd8 fd*Z xZS )9r   zBase class for all resources.resourcezClassVar[str]
KEY_PREFIXT)validate_default.zURI of the resource)defaultdescriptionz6Annotated[AnyUrl, UrlConstraints(host_required=False)]r8    zName of the resourcer+   namer&   z!MIME type of the resource contentr"   NzfAnnotated[Annotations | None, Field(description="Optional annotations about the resource's behavior")]r   zAnnotated[SkipJsonSchema[AuthCheck | list[AuthCheck] | None], Field(description='Authorization checks for this resource', exclude=True)]auth)rp   versiontitlern   iconsr"   tagsr   r$   taskrq   c               L    ddl m}  |j                  |||||||||	|
|||      S )Nr   r   )fnr8   rp   rr   rs   rn   rt   r"   ru   r   r$   rv   rq   )#fastmcp.resources.function_resourcer   from_function)clsrx   r8   rp   rr   rs   rn   rt   r"   ru   r   r$   rv   rq   r   s                  r5   rz   zResource.from_function   sF    $	
 .--##
 	
r6   before)modec                    |r|S y)z&Set default MIME type if not provided.r&    )r{   r"   s     r5   set_default_mime_typezResource.set_default_mime_type  s     r6   afterc                    | j                   r	 | S | j                  rt        | j                        | _         | S t        d      )z*Set default name from URI if not provided.z#Either name or uri must be provided)rp   r8   r+   
ValueErrorr2   s    r5   set_default_namezResource.set_default_name   sB     99
 	 XXDHHDI  BCCr6   c                    K   t        d      w)a
  Read the resource content.

        Subclasses implement this to return resource data. Supported return types:
            - str: Text content
            - bytes: Binary content
            - ResourceResult: Full control over contents and result-level meta
        z Subclasses must implement read())NotImplementedErrorr   s    r5   readzResource.read+  s      ""DEEs   c                   t        |t              r|S t        |t        t        f      r,t        t	        || j
                  | j                        g      S t        |t        t        z  t        z  t        z  t        z  t        z        s|ht        |t              r|rt        |d   t              sCt        t	        t        j                  |      | j
                  xs d| j                        g      S t        |      S )a$  Convert a raw result to ResourceResult.

        This is used in two contexts:
        1. In _read() to convert user function return values to ResourceResult
        2. In tasks_result_handler() to convert Docket task results to ResourceResult

        Handles ResourceResult passthrough and converts raw values using
        ResourceResult's normalization.  When the raw value is a plain
        string or bytes, the resource's own ``mime_type`` is forwarded so
        that ``ui://`` resources (and others with non-default MIME types)
        don't fall back to ``text/plain``.

        The resource's component-level ``meta`` (e.g. ``ui`` metadata for
        MCP Apps CSP/permissions) is propagated to each content item so
        that hosts can read it from the ``resources/read`` response.
        )r"   r$   r   r)   )r*   rN   r+   r,   r   r"   r$   rY   rU   rZ   r[   r\   r]   r^   r_   )r2   	raw_values     r5   convert_resultzResource.convert_result7  s    " i0
 i#u.! dnn499UV  y$+"5";e"Cd"JK y$'9Q<9!#

9-"&.."F4F!YY  i((r6   c                   K   y wrf   r   r2   	task_metas     r5   _readzResource._readm  s	     EH   c                   K   y wrf   r   r   s     r5   r   zResource._readp  s	     NQr   c                   K   ddl m}  || dd|       d{   }|r|S | j                          d{   }| j                  |      S 7 17 w)a  Server entry point that handles task routing.

        This allows ANY Resource subclass to support background execution by setting
        task_config.mode to "supported" or "required". The server calls this
        method instead of read() directly.

        Args:
            task_meta: If provided, execute as a background task and return
                CreateTaskResult. If None (default), execute synchronously and
                return ResourceResult.

        Returns:
            ResourceResult when task_meta is None.
            CreateTaskResult when task_meta is provided.

        Subclasses can override this to customize task routing behavior.
        For example, FastMCPProviderResource overrides to delegate to child
        middleware without submitting to Docket.
        r   )check_background_taskrj   N)	component	task_type	argumentsr   )fastmcp.server.tasks.routingr   r   r   )r2   r   r   task_resultresults        r5   r   zResource._reads  s[     , 	G1jDI
 
  yy{"""6**
 #s   AA
AAAAc                   t        |j                  d| j                        |j                  d| j                        |j                  d| j                        |j                  d| j
                        |j                  d| j                        |j                  d| j                        |j                  d| j                        |j                  d| j                               	      S )
z'Convert the resource to an SDKResource.rp   r8   rn   r:   rs   rt   r   r;   )rp   r8   rn   r:   rs   rt   r   r;   )
SDKResourcegetrp   r8   rn   r"   rs   rt   r   get_meta)r2   	overridess     r5   to_mcp_resourcezResource.to_mcp_resource  s     vtyy1eTXX.!mT5E5EF]]:t~~>--4--4!mT5E5EF--
 	
r6   c           
         | j                   j                   d| j                  d| j                  d| j                  d| j
                   d
S )Nz(uri=z, name=z, description=z, tags=))r4   rF   r8   rp   rn   ru   r   s    r5   __repr__zResource.__repr__  sb    ..))*%|7499-~^b^n^n]qqxy}  zC  zC  yD  DE  F  	Fr6   c                t    | j                  t        | j                              }| d| j                  xs d S )z1The globally unique lookup key for this resource.@ro   )make_keyr+   r8   rr   )r2   base_keys     r5   keyzResource.key  s5     ==TXX/1T\\/R011r6   c                    | j                   j                         sy|j                  | j                  | j                  g       y)z<Register this resource with docket for background execution.N)names)task_configsupports_tasksregisterr   r   )r2   dockets     r5   register_with_docketzResource.register_with_docket  s1    ..0		$((4r6   )fn_keytask_keyc               |   K   |xs | j                   }|r||d<     |j                  |fi |        d{   S 7 w)aC  Schedule this resource for background execution via docket.

        Args:
            docket: The Docket instance
            fn_key: Function lookup key in Docket registry (defaults to self.key)
            task_key: Redis storage key for the result
            **kwargs: Additional kwargs passed to docket.add()
        r   N)r   add)r2   r   r   r   kwargs
lookup_keys         r5   add_to_docketzResource.add_to_docket  sC       'txx
$F5M5ZVZZ
5f57777s   3<:<c                ,    t         |          dddz  S )Nrj   LocalProvider)zfastmcp.component.typezfastmcp.provider.type)r0   get_span_attributes)r2   r4   s    r5   r   zResource.get_span_attributes  s#    w*,&0%40
 
 	
r6   )rx   zCallable[..., Any]r8   zstr | AnyUrlrp   r!   rr   zstr | int | Noners   r!   rn   r!   rt   zlist[Icon] | Noner"   r!   ru   zset[str] | Noner   zAnnotations | Noner$   r#   rv   zbool | TaskConfig | Nonerq   z"AuthCheck | list[AuthCheck] | NonerE   r   )r"   r!   rE   r+   )rE   r   )rE   zstr | bytes | ResourceResult)r   r   rE   rN   rf   )r   NonerE   rN   )r   r   rE   zmcp.types.CreateTaskResult)r   zTaskMeta | NonerE   z+ResourceResult | mcp.types.CreateTaskResult)r   r   rE   r   )rE   r+   )r   r
   rE   r   )
r   r
   r   r!   r   r!   r   r   rE   r   )rE   zdict[str, Any]) rF   rG   rH   rI   rk   rJ   r   model_configr   r8   rp   r"   r   rq   classmethodrz   r   r   r   r   r   r   r	   r   r   r   propertyr   r   r   r   rK   rL   s   @r5   r   r      sO   ' *J*t4LBG!6CC	?  b.DED#E7Is  	    	 	  
   $( "&#' $ $*.&*)-37#
#
 #

 #
 "#
 #
  #
 !#
 #
 #
 (#
 $#
 '#
 1#
  
!#
 #
J [x0  1 '" #
F	%
F4)l H HQ Q ,0 +( +	4 +D

 

&F 2 2
5 "#88 	8
 8 8 
8*
 
r6   r   )r   r   rN   c                    ddd}| |v rLddl }ddl}|j                  j                  r|j	                  d|  dt
        d	       dd
lm} t        ||       S t        dt        d|       )z2Deprecated re-exports for backwards compatibility.r   rj   )r   rj   r   Nz
Importing zh from fastmcp.resources.resource is deprecated. Import from fastmcp.resources.function_resource instead.   )
stacklevel)function_resourcezmodule z has no attribute )warningsfastmcpsettingsdeprecation_warningswarnr   fastmcp.resourcesr   getattrAttributeErrorrF   )rp   deprecated_exportsr   r   r   s        r5   __getattr__r     s     /
 !!00MMTF #K L)	   	8($//
78,.@I
JJr6   )rp   r+   rE   r   )3rI   
__future__r   rA   r^   collections.abcr   typingr   r   r   r   r	   	mcp.typesr=   r   r
   docket.executionr   ry   r   pydanticr-   r   r   r   r   r   r   r   r   r   r   pydantic.json_schemar   typing_extensionsr   fastmcp.exceptionsr   fastmcp.utilities.authorizationr   fastmcp.utilities.componentsr   fastmcp.utilities.tasksr   r   	BaseModelr   rN   __all__r   r   r6   r5   <module>r      s    8 "   $ D D *D   ' -  0 " 8 5 9 8Oh(( Od^
X'' ^
Bv
 v
rKr6   