
    k7iR                        S r SSKJrJrJr  SSKJrJrJrJ	r	J
r
JrJrJr  SSKJr  SSKJr  SSKJr  SSKJ	r  SSKJ
r  SS	KJr  SS
KJr  SSKJr  SSKJrJr  SSKJr  SSKJrJrJrJ r J!r!J"r"  SSK#J$r$J%r%  \" \&5      r'\" S\\5      r(\" S\\5      r)\" S\
\5      r*\" S\\5      r+\" S\\5      r,\" S\\5      r-\" S\\5      r.\" S\	\5      r/S\0\1\4   S\2\   4S jr3 " S S\\(\*\)\+\,\-\.\/4   5      r4SS/r5g) 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                    U R                  SS5      n UR                  S5      (       aw  [        R                  " U 5      n[        R                  SUR                   35        [        U[        [        [        [        [        [        [        U5	      nUR                  5       $ [         R                  " U 5      n[        R                  SUR                   35        [        U["        [$        [&        [(        [*        [,        [.        U5	      nUR                  5       $ ! [0         aT  n[        R3                  SU 35        UR5                  5       n[        R3                  SU 35        [7        SU 35      UeS	nAff = f)
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_detailss          g/home/james-whalen/.local/lib/python3.13/site-packages/fastmcp/experimental/utilities/openapi/parser.pyparse_openapi_to_http_routesr@   7   sM    #&&y"5O)L%%e,,#22<@JLLB:CUCUBVW #
F <<>! !//=JLLB:CUCUBVW #
F <<>! L9!=>
*=/:;3M?CD!K	Ls    BD !A6D 
E6"AE11E6c                   "   \ rS rSrSrS\S\\   S\\   S\\	   S\\
   S\\   S	\\   S
\\   S\4S jrS\S\4S jrS\S\4S jrS\S\4S jr  S*S\\   S-  S\\   S-  S\\   4S jjrS\S\S-  4S jrS\S\4S jrS\\\4   S\\\4   S-  4S jrS\\\4   S-  S\\\ 4   4S jr! S+S\S \\\4   S!\"\   S-  S\"\   4S" jjr#S#\\   S$\S-  S \\\4   S\\\4   4S% jr$S&\\\ 4   S \\\4   S\\\4   4S' jr%S\\&   4S( jr'S)r(g),r-   m   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_clsr9   c
                 p    Xl         X l        X0l        X@l        XPl        X`l        Xpl        Xl        Xl        g)z?Initialize the parser with the OpenAPI schema and type classes.N)	r%   rC   rD   rE   rF   rG   rH   rI   r9   )
selfr%   rC   rD   rE   rF   rG   rH   rI   r9   s
             r?   __init__OpenAPIParser.__init__{   s8     *$* 0(**.    param_inr#   c                 F    US;   a  U$ [         R                  SU S35        g)z@Convert string parameter location to our ParameterLocation type.)pathqueryheadercookiezUnknown parameter location: z, defaulting to 'query'rR   )r+   warning)rK   rO   s     r?   _convert_to_parameter_location,OpenAPIParser._convert_to_parameter_location   s*    <<O5hZ?VWXrN   itemc                 r   [        XR                  5      (       Ga  UR                  n[        U[        5      (       d  U$  UR	                  S5      (       d  [        SU 35      eUR                  S5      R                  S5      nU R                  nU GH:  nUR                  5       (       a$  [        U[        5      (       a  U[        U5         nO[        U[        5      (       a  XTR                  R                  ;   a  [        XES5      nOUR                   (       a  XTR                   ;   a  UR                   U   nO}US:X  a  [#        US5      (       a  UR$                  nOY[#        XE5      (       a  [        XES5      nO<SnO9[        U[&        5      (       a  UR)                  U5      nO[        SU SU S35      eUb  GM+  [        S	U S
U S35      e   [        X@R                  5      (       a  U R+                  U5      $ U$ U$ ! [,        [.        [0        [2        [
        4 a  n[        SU SU 35      UeSnAff = f)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 '': )
isinstancerC   refstrr(   r8   stripsplitr%   isdigitlistintr   	__class__model_fieldsgetattrmodel_extrahasattrr[   dictr'   _resolve_refAttributeErrorKeyError
IndexError	TypeError)rK   rX   ref_strpartstargetpartr=   s          r?   rl   OpenAPIParser._resolve_ref   s
   d..//hhGgs++,Y))$//$I'S   d+11#6!D||~~*VT*B*B!'D	!2#FI66#3#3#@#@@%,V4%@F#//D<N<N4N%+%7%7%=F  $|38U8U)/):):!(!6!6)0t)D)-#FD11!'D!1(4TF:J7)STU  ~(.tf4I'RST 3 "< f&8&899,,V44  #Hj)ZP Y #@	QC!PQWXXYs%    E8H  =>H  <H   H6H11H6
schema_objc                     U R                  U5      n[        X R                  5      (       a  UR                  SSSS9nO<[        U[        5      (       a  UnO$[
        R                  S[        U5       S35        0 n[        U5      nU$ ! [         a3  nS[        U5      ;   a  e [
        R                  SU 3SS	9  0 s S
nA$ S
nAf[         a#  n[
        R                  SU 3SS	9  0 s S
nA$ S
nAff = f)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)rl   r^   rD   
model_dumprk   r+   rU   typer   r8   r`   r6   	Exception)rK   rv   resolved_schemaresultr=   s        r?   _extract_schema_as_dict%OpenAPIParser._extract_schema_as_dict   s    	"//
;O/??;;(33$T 4  OT22(;D<Q;RRij  ,F3FM 	>#a&HLL=aSAELRI 	LL=aSAELRI	s0   BB 
C0(C :C0 C0C+%C0+C0Noperation_paramspath_item_paramsc                    / n0 nU=(       d    / U=(       d    / -   nU GHs  n U R                  U5      n[        XpR                  5      (       d$  [        R	                  S[        U5       S35        MT  UR                  nSSKJn	  [        X5      (       a  UR                  OUn
U R                  U
5      nUR                  nUR                  U
4nX;   a  M  SXM'   0 nU(       aj  U R                  U5      nU R                  U5      n[        XR                  5      (       d-  [        US5      (       a  UR                   b  UR                   US'   O[        US5      (       a  UR"                  (       a  [%        ['        UR"                  R)                  5       5      S5      nU(       a  [        US	5      (       a  UR*                  (       av  UR*                  nU R                  U5      nU R                  U5      n[        UU R                  5      (       d-  [        US5      (       a  UR                   b  UR                   US'   [-        US
S5      n[-        USS5      n[/        UR                  UUR0                  UUR2                  UUS9nUR5                  U5        GMv     U$ ! [6         a>  n[-        US[-        USS5      5      n[        R9                  SU SU 3SS9   SnAGM  SnAff = f)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   r_   unknownzFailed to extract parameter 'r]   Fr}   )rl   r^   rE   r+   rU   r   rO   enumr   valuerV   param_schemar   r   rC   rj   r   r   nextitervaluesr   rh   r   r   r   appendr   r6   )rK   r   r   extracted_paramsseen_params
all_paramsparam_or_ref	parameterrO   r   param_in_strparam_locationparam_schema_obj	param_keyparam_schema_dictr   first_media_typemedia_schemaresolved_media_schemar   r   
param_infor=   
param_names                           r?   _extract_parameters!OpenAPIParser._extract_parameters   s    13  	 ',"1A1GRH
&LR --l;	!)-?-?@@NNB4	?BSS^_  %--% '1&@&@HNNh  "&!D!D\!R#,#9#9  '^^\:	+)-& %'!#(,(D(DEU(V% '+&7&78H&IO&8J8JKK#OY??+33?7F7N7N))4Y	22y7H7H'+D1B1B1I1I1K,Ld'S$(#$46IJJ,>>'7'I'I,0,H,H,V) 150A0A,0O- *+@$BTBT U U '(=y I I 5 = = I;P;X;X-i8 ")Y=	7D9 +"+&//, ) 5 5#
 !''
3Y 'j    $ &',y*Q
 3J<s1#FQV   	s&   AJ2A JF=J
K "2KK request_body_or_refc                    U(       d  g U R                  U5      n[        X R                  5      (       d#  [        R	                  S[        U5       S35        g[        UR                  UR                  S9n[        US5      (       a  UR                  (       a}  UR                  R                  5        H_  u  pEU(       d  M  [        US5      (       d  M!  UR                  (       d  M4   U R                  UR                  5      nUUR                  U'   Ma     U$ ! [         a6  nS[!        U5      ;   a  e [        R#                  SU S	U 35         SnAM  SnAf[$         a&  n[        R#                  SU S	U 35         SnAM  SnAff = f! [         aA  nS[!        U5      ;   a  e ['        US
S5      n[        R#                  SU S	U 3SS9   SnAgSnAf[$         a1  n['        US
S5      n[        R#                  SU S	U 3SS9   SnAgSnAff = f)z-Extract and resolve request body information.Nz*Expected RequestBody after resolving, got z. Returning None.)r   r   r   r   r|   )Failed to extract schema for media type 'r]   r_   r   z Failed to extract request body 'Fr}   )rl   r^   rF   r+   rU   r   r   r   r   rj   r   itemsr   r   content_schemar8   r`   r6   r   rh   )	rK   r   request_bodyrequest_body_infomedia_type_strmedia_type_objschema_dictr=   ref_names	            r?   _extract_request_body#OpenAPIParser._extract_request_bodyS  s   ";	,,-@ALl,A,ABB@lAS@TTef  !0%..(44! |Y//L4H4H6B6J6J6P6P6R2N&#N4GHH*<<<*.*F*F . @ @+K !, .<<^L 7S6 %$  * NRU !S   !&"LL"KNK[[^_`^a b   ) "LL"KNK[[^_`^a b   	>#a&H2E9EHLL28*CsCe    	2E9EHLL28*CsCe   	ss   AF A$F  F F '*DF 
F!+EF FF :F  FF 
H7GH'HHstatus_codec                      [        U5      nSUs=:*  =(       a    S:  $ s  $ ! [        [        4 a    UR                  5       S;   s $ f = f)z>Check if a status code represents a successful response (2xx).   i,  )r   2xx)re   r8   rp   lower)rK   r   code_ints      r?   _is_success_status_code%OpenAPIParser._is_success_status_code  sS    	=;'H(((S((((I& 	=$$&*<<<	=s   " " #AAoperation_responsesc                     U(       d  g/ SQnU H  nX1;   d  M
  X1U   4s  $    UR                  5        H   u  pEU R                  U5      (       d  M  XE4s  $    g)zTGet the primary success response for an MCP tool. We only need one success response.N)200201202204207)r   r   )rK   r   priority_codescoder   resp_or_refs         r?   _get_primary_success_response+OpenAPIParser._get_primary_success_response  si     # = #D*$788 #
 )<(A(A(C$K++K88#11 )D
 rN   c           
         0 nU(       d  U$ U R                  U5      nU(       d  [        R                  S5        U$ Uu  pE[        R                  SU 35         U R                  U5      n[	        X`R
                  5      (       d'  [        R                  SU S[        U5       S35        U$ [        UR                  S9n[        US5      (       Ga  UR                  (       a  UR                  R                  5        H  u  pU	(       d  M  [        U	S5      (       d  M!  U	R                  (       d  M4   S	n
U	R                  n[	        XR                  5      (       aK  UR                  n[	        U[         5      (       a*  UR#                  S
5      (       a  UR%                  S5      S   n
U R'                  U5      nU
(       a  U
US'   XR(                  U'   M     Xr[!        U5      '   U$ ! [*         a:  nS[!        U5      ;   a  e [        R-                  SU SU SU 35         S	nAGM%  S	nAf[.         a*  n[        R-                  SU SU SU 35         S	nAGMW  S	nAff = f! [*         aE  nS[!        U5      ;   a  e [1        USS5      n[        R-                  SU SU SU 3SS9   S	nAU$ S	nAf[.         a5  n[1        USS5      n[        R-                  SU SU SU 3SS9   S	nAU$ S	nAff = f)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/rZ   x-fastmcp-top-level-schemar|   r   z' in response : r_   r   z+Failed to extract response for status code z from reference 'r]   Fr}   )r   r+   r,   rl   r^   rG   rU   r   r   r   rj   r   r   r   rC   r_   r`   r(   rb   r   r   r8   r6   r   rh   )rK   r   extracted_responsesprimary_responser   r   response	resp_infor   r   top_level_schema_namer   rq   r   r=   r   s                   r?   _extract_responses OpenAPIParser._extract_responses  s!    8:"&&  ==>QRLLVW&&#3 7}EFH	((5Hh(9(9::H V>**FH +* %1E1EFI x++0@0@6>6F6F6L6L6N2N&#N4GHH*<<< 481+9+K+KL),8J8JKK*6*:*:#-gs#;#;@R@R$;A" A" =DMM#<Nr<R$9*.*F*F|*TK4$9 !,,H I HS44^D/ 7OP 5>K 01& #"G  * 	NRU !S   !&"LL"KNK[ \//:m2aS!B   ) "LL"KNK[ \//:m2aS!B   		>#a&H{E9=HLL=k] K##+*Cs4   #"  	{E9=HLL=k] K##+*Cs4   #"	su   AI *AI I I /BG I  
I*.HI I,I
I II 
K%#:J##K%0*K  K%r   all_schemas	collectedc                 F   ^^^ Tc
  [        5       mUUU4S jmT" U5        T$ )a,  
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
c                   > [        U [        5      (       a  SU ;   at  [        U S   [        5      (       a\  U S   nUR                  S5      (       a  UR	                  S5      S   nOgTb(  UT;  a"  UT;   a  TR                  U5        T" TU   5        U R                  5        H  nT" U5        M     g[        U [        5      (       a  U  H  nT" U5        M     gg)z%Recursively find all $ref references.z$ref)z#/$defs/r   rZ   r   N)r^   rk   r`   r(   rb   addr   rd   )objr_   schema_namer   rX   r   r   	find_refss        r?   r   =OpenAPIParser._extract_schema_dependencies.<locals>.find_refs'  s    #t$$S=ZFS%A%Af+C~~&KLL&)iinR&8 "-'y8';6!k2!+k":; !ZZ\Ee$ *C&&DdO   'rN   )set)rK   r   r   r   r   s     ``@r?   _extract_schema_dependencies*OpenAPIParser._extract_schema_dependencies  s'    " I	$8 	&rN   
parametersr   c                    [        5       nU HC  nUR                  (       d  M  U R                  UR                  U5      nUR                  U5        ME     U(       aT  UR                  (       aC  UR                  R                  5        H%  nU R                  Xs5      nUR                  U5        M'     U Vs0 s H  oU;   d  M
  XU   _M     sn$ s  snf )a  
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
)r   schema_r   updater   r   )	rK   r   r   r   needed_schemasparamdepsr   r   s	            r?   "_extract_input_schema_dependencies0OpenAPIParser._extract_input_schema_dependenciesF  s    "   E}}}88T%%d+   L77"."="="D"D"F88U%%d+ #G 1?
0>+BU#Dd##
 	
 
s   3	C 	C	responsesc                 v   [        5       nUR                  5        Hz  nUR                  (       d  M  UR                  R                  5        HF  nSU;   a  US   nXb;   a  UR                  U5        U R	                  XR5      nUR                  U5        MH     M|     U Vs0 s H  oU;   d  M
  XU   _M     sn$ s  snf )z
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   r   r   r   r   r   )	rK   r   r   r   r   r   r   r   r   s	            r?   #_extract_output_schema_dependencies1OpenAPIParser._extract_output_schema_dependenciesj  s      "((*H&&&&.&=&=&D&D&FN3~E&45Q&R&5*..{;  <<&D #))$/ 'G +" 1?
0>+BU#Dd##
 	
 
s   	B6*	B6c                 	   / n[        U R                  S5      (       a  U R                  R                  (       d  [        R	                  S5        / $ 0 n[        U R                  S5      (       a  U R                  R
                  (       a  U R                  R
                  n[        US5      (       a  UR                  (       aw  UR                  R                  5        HY  u  pE [        XPR                  5      (       a&  U R                  U5      nU R                  U5      X$'   MF  U R                  U5      X$'   M[     U(       a=  UR                  5        H)  u  pE[        U[        5      (       d  M  [        U5      X$'   M+     U R                  R                  R                  5        GH  u  p[        XR                  5      (       d'  [        R	                  SU S	[!        U	5       S
35        MG  [        U	S5      (       a  U	R"                  OSn
/ SQnU GH  n[%        XS5      nU(       d  M  [        XR&                  5      (       d  M5  UR)                  5       n U R+                  [%        USS5      U
5      nU R-                  [%        USS5      5      nU R/                  [%        USS5      5      n0 n[        US5      (       aY  UR0                  (       aH  UR0                  R                  5        VVs0 s H!  u  nnUR3                  S5      (       d  M  UU_M#     nnnU R5                  UUU5      nU R7                  UU5      n[9        UU[%        USS5      [%        USS5      [%        USS5      [%        US/ 5      =(       d    / UUUUUUU R:                  S9n [=        USS9u  nnUUl        UUl         URC                  U5        GM     GM!     [        RK                  S$[M        U5       S%35        U$ ! [         a'  n[        R	                  SU SU 35         SnAGM8  SnAff = fs  snnf ! [         a9  n[        R	                  SU SU SU 35        S0 S.Ul        0 Ul          SnANSnAff = f! [D         aI  nS[G        U5      ;   a  e [%        USS5      n[        RI                  SU SU S U S!U 3S"S#9   SnAGM  SnAf[         a9  n[%        USS5      n[        RI                  SU SU S U S!U 3S"S#9   SnAGM  SnAff = f)&z*Parse the OpenAPI schema into HTTP routes.pathsz$OpenAPI schema has no paths defined.r[   schemasz%Failed to extract schema definition 'r]   Nz%Skipping invalid path item for path 'z	' (type: )r   )r'   putpostdeleteoptionsheadpatchtracerequestBodyr   ri   zx-operationIdsummaryr   tags)rQ   methodoperation_idr   r   r  r   r   r   request_schemasresponse_schemas
extensionsr9   F)convert_refsz)Failed to pre-calculate schema for route  r   object)r   
propertiesr|   r   zFailed to process operation z (ID: z): Tr}   zFinished parsing. Extracted z HTTP routes.)'rj   r%   r   r+   rU   r[   r   r   r^   rC   rl   r   r   rk   r   rI   r   r   rh   rH   upperr   r   r   ri   r(   r   r   r   r9   r   flat_param_schemaparameter_mapr   r8   r`   r6   r,   len)rK   routesschema_definitionsr[   r   r   r   r=   path_strpath_item_objpath_level_paramshttp_methodsmethod_lower	operationmethod_upperr   r   r   r  kvinput_schemasoutput_schemasrouteflat_schema	param_mapschema_errorop_errorop_ids                                r?   r5   OpenAPIParser.parse  s   "$t||W--T\\5G5GNNABI  4<<..4<<3J3J00Jz9--*2D2D$.$6$6$<$<$>LD%f.@.@AA.2.?.?.GO7;7S7S /8.4 8<7S7S &8.4 %?"  2 8 8 :fd++/Ef/M&, !;
 (,||'9'9'?'?'A#Hm-?-?@@;H:YtTaObNccde  =,77 (( 	L !-#MF	9I7I7I!J!J#/#5#5#7LT%)%=%=#I|TBDU&
 -1,F,F#I}dC-) %)$;$;#I{DA%	 &(
"9m<<AVAV -6,A,A,G,G,I*,IDAq#$<<#5 !%1,I ' * )-(O(O&-.)
 *.)Q)Q%.* !*!)#/)0M4)P$+Iy$$G(/	=$(O!(FB!?!E2'1):&/,9-;'1,0,@,@!"55T %-262K 7BE32;E/ e,U !-1 (Bj 	3CK=NOG % CD6QCP v*T  ) 	5"NN"KL>YZ[cZddfgsft u
 )1.07E3 35E//	5 & 
Jc$O  " '	=) L:<.(SYZ_Y``cdlcmn%) %   %  '	=) L:<.(SYZ_Y``cdlcmn%) %  s    >O& O&BQ&'P
P
A<Q&P 'Q&&
P0PPQ& 
Q#*/QQ&Q##Q&&
S:0=R44S:-S55S:)	r%   r9   rH   rE   rI   rC   rF   rG   rD   )NN)N))__name__
__module____qualname____firstlineno____doc__r   r   r   r   r   r   r   r    r!   r`   rL   r   rV   r   rl   r   r   rd   r   r   r   r   boolr   rk   tupler   r   r   r   r   r   r   r   r5   __static_attributes__ rN   r?   r-   r-   m   si    f// J'/ M	/
 J'/ |,/ 9o/ J'/ I/ /.s ?P 5 5 5n# * D .2-1a s)d*a  s)d*a  
m		a F@ @SWAW @D=3 =4 =#'S>	sCx4	.\##'S>D#8\#	c<	 \#D &*	11 #s(^1 s8d?	1
 
S1f"
'"
 &,"
 #s(^	"

 
c3h"
H$
\)*$
 #s(^$
 
c3h	$
L[tI [rN   r-   r@   N)6r'  typingr   r   r   openapi_pydanticr   r   r   r	   r
   r   r   r   openapi_pydantic.v3.v3_0r)   r3   r0   r4   r.   r1   r2   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!   rk   r`   rd   r@   r-   __all__r+  rN   r?   <module>r3     s.   N ( (	 	 	 ; > > < > B < 8 / 0 
 
H	 :w
3
)VY
/\9l;
\9l;
~{NCK;7	\9l;
K;7	3LtCH~ 3L$y/ 3Ll~
		~
F "rN   