o
    i"                     @   s  d Z ddlmZmZmZ ddlmZmZ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 dd
lmZ ddlm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$m%Z% ee&Z'edeeZ(edeeZ)ede
eZ*edeeZ+edeeZ,edeeZ-edeeZ.ede	eZ/de0e1ef de2e fddZ3G dd dee(e*e)e+e,e-e.e/f Z4ddgZ5dS ) zHOpenAPI parsing logic for converting OpenAPI specs to HTTPRoute objects.    )AnyGenericTypeVar)OpenAPI	Operation	ParameterPathItem	ReferenceRequestBodyResponseSchema)r   )r   )r   )r   )r	   )r
   )r   )r   )	BaseModelValidationError)
get_logger   )	HTTPRoute
JsonSchemaParameterInfoParameterLocationRequestBodyInfoResponseInfo)_combine_schemas_and_map_params_replace_ref_with_defsTOpenAPITSchema
TReference
TParameterTRequestBody	TResponse
TOperation	TPathItemopenapi_dictreturnc              
   C   s   |  dd}zC|dr+t| }td|j  t|tt	t
tttt|	}| W S t| }td|j  t|ttttttt|	}| W S  tyq } ztd|  | }td|  td| |d	}~ww )
z
    Parses an OpenAPI schema dictionary into a list of HTTPRoute objects
    using the openapi-pydantic library.

    Supports both OpenAPI 3.0.x and 3.1.x versions.
    openapi z3.0z0Successfully parsed OpenAPI 3.0 schema version: z0Successfully parsed OpenAPI 3.1 schema version: z"OpenAPI schema validation failed: zValidation errors: zInvalid OpenAPI schema: N)get
startswith
OpenAPI_30model_validateloggerdebugr#   OpenAPIParserReference_30	Schema_30Parameter_30RequestBody_30Response_30Operation_30PathItem_30parser   r	   r   r   r
   r   r   r   r   errorerrors
ValueError)r!   openapi_version
openapi_30parser
openapi_31eerror_details r=   s/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/fastmcp/experimental/utilities/openapi/parser.pyparse_openapi_to_http_routes7   sT   






r?   c                   @   s  e Zd ZdZdedee dee dee dee	 dee
 dee d	ee d
efddZdedefddZdedefddZdedefddZ		d5dee dB dee dB dee fddZdededB fddZdedefd d!Zd"eeef deeef dB fd#d$Zd"eeef dB deeef fd%d&Z 	d6d'ed(eeef d)e!e dB de!e fd*d+Z"d,ee d-edB d(eeef deeef fd.d/Z#d0eeef d(eeef deeef fd1d2Z$dee% fd3d4Z&dS )7r+   z[Unified parser for OpenAPI schemas with generic type parameters to handle both 3.0 and 3.1.r#   reference_cls
schema_clsparameter_clsrequest_body_clsresponse_clsoperation_clspath_item_clsr7   c
           
      C   s:   || _ || _|| _|| _|| _|| _|| _|| _|	| _dS )z?Initialize the parser with the OpenAPI schema and type classes.N)	r#   r@   rA   rB   rC   rD   rE   rF   r7   )
selfr#   r@   rA   rB   rC   rD   rE   rF   r7   r=   r=   r>   __init__{   s   
zOpenAPIParser.__init__param_inr"   c                 C   s"   |dv r|S t d| d dS )z@Convert string parameter location to our ParameterLocation type.)pathqueryheadercookiezUnknown parameter location: z, defaulting to 'query'rK   )r)   warning)rG   rI   r=   r=   r>   _convert_to_parameter_location   s   z,OpenAPIParser._convert_to_parameter_locationitemc                 C   s  t || jr|j}t |ts|S z|dstd| |dd}| j}|D ]s}|	 r<t |t
r<|t| }nRt |trx||jjv rNt||d}n@|jr\||jv r\|j| }n2|dkrit|dri|j}n%t||rut||d}nd}nt |tr||}ntd| d| d|du rtd	| d
| dq*t || jr| |W S |W S  tttttfy } ztd| d| |d}~ww |S )z.Resolves a reference to its target definition.z#/z/External or non-local reference not supported: /N
componentszCannot traverse part 'z' in reference ''zReference part 'z' not found in path 'zFailed to resolve reference '': )
isinstancer@   refstrr&   r6   stripsplitr#   isdigitlistintr   	__class__model_fieldsgetattrmodel_extrahasattrrR   dictr%   _resolve_refAttributeErrorKeyError
IndexError	TypeError)rG   rP   ref_strpartstargetpartr;   r=   r=   r>   rc      sT   




zOpenAPIParser._resolve_ref
schema_objc              
   C   s   z0|  |}t|| jr|jdddd}nt|tr|}ntdt| d i }t|}|W S  t	yU } zdt
|v r? tjd| dd	 i W  Y d
}~S d
}~w tyr } ztjd| dd	 i W  Y d
}~S d
}~ww )z1Resolves a schema and returns it as a dictionary.jsonT)modeby_aliasexclude_nonez%Expected Schema after resolving, got z. Returning empty dict.-External or non-local reference not supportedz"Failed to extract schema as dict: Fexc_infoN)rc   rU   rA   
model_dumprb   r)   rN   typer   r6   rW   r4   	Exception)rG   rl   resolved_schemaresultr;   r=   r=   r>   _extract_schema_as_dict   s2   

z%OpenAPIParser._extract_schema_as_dictNoperation_paramspath_item_paramsc                 C   s  g }i }|pg |p
g  }|D ]}z|  |}t|| js)tdt| d W q|j}ddlm}	 t||	r:|j	n|}
| 
|
}|j}|j|
f}||v rOW qd||< i }|rw| |}|  |}t|| jsvt|drv|jdurv|j|d< n>t|dr|jrtt|j d}|rt|d	r|jr|j}| |}|  |}t|| jst|dr|jdur|j|d< t|d
d}t|dd}t|j||j||j||d}|| W q ty } zt|dt|dd}tjd| d| dd W Y d}~qd}~ww |S )z<Extract and resolve parameters from operation and path item.z(Expected Parameter after resolving, got z. Skipping.r   )EnumTdefaultNcontentmedia_type_schemaexplodestyle)namelocationrequiredschemadescriptionr   r   r   rV   unknownzFailed to extract parameter 'rT   Frr   )rc   rU   rB   r)   rN   ru   rI   enumr|   valuerO   param_schemar   ry   r@   ra   r}   r~   nextitervaluesr   r_   r   r   r   appendrv   r4   )rG   rz   r{   extracted_paramsseen_params
all_paramsparam_or_ref	parameterrI   r|   param_in_strparam_locationparam_schema_obj	param_keyparam_schema_dictrw   first_media_typemedia_schemaresolved_media_schemar   r   
param_infor;   
param_namer=   r=   r>   _extract_parameters   s   












	z!OpenAPIParser._extract_parametersrequest_body_or_refc           	      C   s  |sdS z|  |}t|| jstdt| d W dS t|j|jd}t	|dr|j
r|j
 D ]\\}}|rt	|dr|jrz| |j}||j|< W q3 tyr } zdt|v r] td| d	|  W Y d}~q3d}~w ty } ztd| d	|  W Y d}~q3d}~ww q3|W S  ty } z!dt|v r t|d
d}tjd| d	| dd W Y d}~dS d}~w ty } zt|d
d}tjd| d	| dd W Y d}~dS d}~ww )z-Extract and resolve request body information.Nz*Expected RequestBody after resolving, got z. Returning None.)r   r   r~   r   rq   )Failed to extract schema for media type 'rT   rV   r   z Failed to extract request body 'Frr   )rc   rU   rC   r)   rN   ru   r   r   r   ra   r~   itemsr   ry   content_schemar6   rW   r4   rv   r_   )	rG   r   request_bodyrequest_body_infomedia_type_strmedia_type_objschema_dictr;   ref_namer=   r=   r>   _extract_request_bodyS  sz   
z#OpenAPIParser._extract_request_bodystatus_codec              	   C   sH   zt |}d|  kodk W S   W S  ttfy#   | dv  Y S w )z>Check if a status code represents a successful response (2xx).   i,  )r}   2xx)r\   r6   rg   lower)rG   r   code_intr=   r=   r>   _is_success_status_code  s   z%OpenAPIParser._is_success_status_codeoperation_responsesc                 C   s^   |sdS g d}|D ]}||v r||| f  S q
|  D ]\}}| |r,||f  S qdS )zTGet the primary success response for an MCP tool. We only need one success response.N)200201202204207)r   r   )rG   r   priority_codescoder   resp_or_refr=   r=   r>   _get_primary_success_response  s   
z+OpenAPIParser._get_primary_success_responsec                 C   st  i }|s|S |  |}|std |S |\}}td|  z| |}t|| js=td| dt| d |W S t|j	d}t
|dr|jr|j D ]\}}	|	rt
|	dr|	jrz1d	}
|	j}t|| jr~|j}t|tr~|d
r~|dd }
| |}|
r|
|d< ||j|< W qP ty } zdt|v r td| d| d|  W Y d	}~qPd	}~w ty } ztd| d| d|  W Y d	}~qPd	}~ww qP||t|< W |S  ty } z$dt|v r t|dd}tjd| d| d| dd W Y d	}~|S d	}~w ty9 } zt|dd}tjd| d| d| dd W Y d	}~|S d	}~ww )zcExtract and resolve response information. Only includes the primary success response for MCP tools.z;No success responses found, tool will have no output schemaz Using primary success response: z2Expected Response after resolving for status code z, got z. Returning empty responses.)r   r~   r   N#/components/schemas/rQ   x-fastmcp-top-level-schemarq   r   z' in response : rV   r   z+Failed to extract response for status code z from reference 'rT   Frr   )r   r)   r*   rc   rU   rD   rN   ru   r   r   ra   r~   r   r   r@   rV   rW   r&   rY   ry   r   r6   r4   rv   r_   )rG   r   extracted_responsesprimary_responser   r   response	resp_infor   r   top_level_schema_namer   rh   r   r;   r   r=   r=   r>   _extract_responses  s   



z OpenAPIParser._extract_responsesr   all_schemas	collectedc                    s*   du rt   fdd| S )al  
        Extract all schema names referenced by a schema (including transitive dependencies).

        Args:
            schema: The schema to analyze
            all_schemas: All available schema definitions
            collected: Set of already collected schema names (for recursion)

        Returns:
            Set of schema names that are referenced
        Nc                    s   t | trGd| v r:t | d tr:| d }|dr!|dd }ndS dur:|vr:| v r:|  |  |  D ]}| q>dS t | trU| D ]}| qNdS dS )z%Recursively find all $ref references.z$ref)z#/$defs/r   rQ   r   N)rU   rb   rW   r&   rY   addr   r[   )objrV   schema_namer   rP   r   r   	find_refsr=   r>   r   '  s&   





z=OpenAPIParser._extract_schema_dependencies.<locals>.find_refs)set)rG   r   r   r   r=   r   r>   _extract_schema_dependencies  s
   z*OpenAPIParser._extract_schema_dependencies
parametersr   c                    sp   t  }|D ]}|jr| |j }|| q|r/|jr/|j D ]}| | }|| q! fdd|D S )aZ  
        Extract only the schema definitions needed for input (parameters and request body).

        Args:
            parameters: Route parameters
            request_body: Route request body
            all_schemas: All available schema definitions

        Returns:
            Dictionary containing only the schemas needed for input
        c                       i | ]}| v r| | qS r=   r=   .0r   r   r=   r>   
<dictcomp>f      zDOpenAPIParser._extract_input_schema_dependencies.<locals>.<dictcomp>)r   schema_r   updater   r   )rG   r   r   r   needed_schemasparamdepsr   r=   r   r>   "_extract_input_schema_dependenciesF  s   


z0OpenAPIParser._extract_input_schema_dependencies	responsesc                    s   |r si S t  }| D ]6}|jsq|j D ]*}| | }|| |d}t|trB| v rB|| | j |  |d qq fdd|D S )a  
        Extract only the schema definitions needed for outputs (responses).

        Args:
            responses: Route responses
            all_schemas: All available schema definitions

        Returns:
            Dictionary containing only the schemas needed for outputs
        r   )r   c                    r   r=   r=   r   r   r=   r>   r     r   zEOpenAPIParser._extract_output_schema_dependencies.<locals>.<dictcomp>)	r   r   r   r   r   r%   rU   rW   r   )rG   r   r   r   r   r   r   r   r=   r   r>   #_extract_output_schema_dependenciesj  s,   



z1OpenAPIParser._extract_output_schema_dependenciesc                 C   s  g }t | jdr| jjstd g S i }t | jdrn| jjrn| jj}t |drn|jrn|j D ]=\}}zt|| j	rH| 
|}| |||< n| |||< W q0 tym } ztd| d|  W Y d}~q0d}~ww |r| D ]\}}t|trt|||< qt| jj D ]E\}}	t|	| jstd| d	t|	 d
 qt |	dr|	jnd}
g d}|D ]}t|	|d}|rt|| jr| }z| t|dd|
}| t|dd}| t|dd}i }t |dr|jrdd |j D }| |||}| ||}t||t|ddt|ddt|ddt|dg p#g ||||||| jd}zt|dd\}}||_||_W n* tyh } ztd| d| d|  di d|_i |_W Y d}~nd}~ww | | W q t!y } z'dt"|v r t|dd}tj#d | d| d!| d"| d#d$ W Y d}~qd}~w ty } zt|dd}tj#d | d| d!| d"| d#d$ W Y d}~qd}~ww qqt$d%t%| d& |S )'z*Parse the OpenAPI schema into HTTP routes.pathsz$OpenAPI schema has no paths defined.rR   schemasz%Failed to extract schema definition 'rT   Nz%Skipping invalid path item for path 'z	' (type: )r   )r%   putpostdeleteoptionsheadpatchtracerequestBodyr   r`   c                 S   s    i | ]\}}| d r||qS )zx-)r&   )r   kvr=   r=   r>   r     s    z'OpenAPIParser.parse.<locals>.<dictcomp>operationIdsummaryr   tags)rJ   methodoperation_idr   r   r   r   r   r   request_schemasresponse_schemas
extensionsr7   F)convert_refsz)Failed to pre-calculate schema for route  r   object)ru   
propertiesrq   r   zFailed to process operation z (ID: z): Trr   zFinished parsing. Extracted z HTTP routes.)&ra   r#   r   r)   rN   rR   r   r   rU   r@   rc   ry   rv   rb   r   rF   ru   r   r_   rE   upperr   r   r   r`   r   r   r   r7   r   flat_param_schemaparameter_mapr   r6   rW   r4   r*   len)rG   routesschema_definitionsrR   r   r   rw   r;   path_strpath_item_objpath_level_paramshttp_methodsmethod_lower	operationmethod_upperr   r   r   r   input_schemasoutput_schemasrouteflat_schema	param_mapschema_errorop_errorop_idr=   r=   r>   r3     s   













]zOpenAPIParser.parse)NN)N)'__name__
__module____qualname____doc__r   ru   r   r   r   r   r   r   r    rW   rH   r   rO   r   rc   r   ry   r[   r   r   r   r   boolr   rb   tupler   r   r   r   r   r   r   r   r3   r=   r=   r=   r>   r+   m   s    	

7"


cB	



b


3


$



)r+   N)6r  typingr   r   r   openapi_pydanticr   r   r   r   r	   r
   r   r   openapi_pydantic.v3.v3_0r'   r1   r.   r2   r,   r/   r0   r-   pydanticr   r   fastmcp.utilities.loggingr   modelsr   r   r   r   r   r   r   r   r   r
  r)   r   r   r   r   r   r   r   r    rb   rW   r[   r?   r+   __all__r=   r=   r=   r>   <module>   s\    ( 
6     K