
    +}&iyk                     z   d dl Z d dlZd dlZd dlmZ d dlmZmZ d dl	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 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"m#Z# d
dlm$Z$m%Z% d
dl&m'Z'm(Z(m)Z)m*Z*  ejV                  e,      Z- ej\                  d      Z/d Z0d Z1 G d de      Z G d d      Z2y)    N)OrderedDictdefaultdict)
URLPatternURLResolver)
versioning)EndpointEnumerator)endpoint_orderingget_pk_name)SchemaGenerator)get_pk_description)api_settings   )openapi)swagger_settings)SwaggerGenerationError)get_basic_type_infoget_queryset_fieldget_queryset_from_view)ReferenceResolverSwaggerDict)force_real_strget_consumesget_producesis_list_viewz{(?P<parameter>\w+)}c                    | D cg c]"  }|j                  d      j                  d      $ }}t        |      }t        |      }|}t	        |      D ]  \  }}|||   k7  s|d | } n ddj                  |      z   S c c}w )N/)stripsplitminmax	enumeratejoin)pathspathsplit_pathss1s2commonics           K/usr/local/footviz/venv/lib/python3.12/site-packages/drf_yasg/generators.pycommon_pathr,       s    :?@$4::c?((-@K@	[	B	[	BF" 11:VF &!!! As   'A<c                 
    | dvS )N>   listcreateupdatedestroyretrievepartial_update )actions    r+   is_custom_actionr6   ,   s           c                   \     e Zd Zd fd	Z fdZ	 d	 fd	Zd Z	 	 	 	 	 d
dZd Zd Z	 xZ
S )r   c                 <    t         t        |   ||       || _        y N)superr   __init__request)selfpatternsurlconfr=   	__class__s       r+   r<   zEndpointEnumerator.__init__8   s     $07Cr7   c                     |j                  d      rt        j                  d|       | j                  t        t
        |   |            S )N)zEurl pattern does not end in $ ('%s') - unexpected things might happen)endswithloggerwarningunescape_pathr;   r   get_path_from_regex)r>   
path_regexrA   s     r+   rH   z&EndpointEnumerator.get_path_from_regex<   sH    s#NNW !!$d?
K
 	
r7   c                 0   t         t        |   ||      syt        | j                  dd       }t        |j
                  dd       }|0t        |t        j                        r|r||j                  d      vryt        |j
                  dt                     yy)NFversionversioning_class:swagger_schemaT)r;   r   should_include_endpointgetattrr=   cls
issubclassr   NamespaceVersioningr   object)	r>   r$   callbackapp_name	namespaceurl_namerK   rL   rA   s	           r+   rO   z*EndpointEnumerator.should_include_endpointF   s     'FtXV$,,	48"8<<1CTJ'Jj<<-
 7)//#*>>8<<!168<Dr7   c                 >   t        |j                  dd      }|t        |t        j                        rit        | j
                  dd      }|rPt        |dd      }d|z  }||vr(t        j                  d|j                  d|d|       |j                  ||      }|S )	a*  If ``request.version`` is not ``None`` and `callback` uses
        ``URLPathVersioning``, this function replaces the ``version`` parameter in
        `path` with the actual version.

        :param str path: the templated path
        :param callback: the view callback
        :rtype: str
        rL   NrK   version_param{%s}zview z  uses URLPathVersioning but URL z has no param )	rP   rQ   rR   r   URLPathVersioningr=   rE   inforeplace)r>   r$   rU   rL   rK   rZ   s         r+   replace_versionz"EndpointEnumerator.replace_versionY   s     #8<<1CTJ'Jj::-
 dllIt<G '(8/9 U & 6 ,KK#<<}> ||M7;r7   c           	         || j                   }g }|
t               }|D ]q  }|t        |j                        z   }t	        |t
              r	 | j                  |      }	|j                  }
|j                  }| j                  |	|
|xs d|xs d|      rT| j                  |	|
      }	|	|v r|j                  |	       | j                  |
      D ]  }|	||
f}|j                  |        t	        |t"              rm| j%                  |j&                  ||r|d|j(                  n|j(                  |r|d|j*                  n|j*                  |      }|j-                  |       Et        j!                  dj/                  t1        |                   t t3        |t4              }|S # t        $ r t        j!                  dd       Y w xY w)	z
        Return a list of all available API endpoints by inspecting the URL conf.

        Copied entirely from super.
         zfailed to enumerate viewT)exc_inforM   )r?   prefixrV   rW   ignored_endpointszunknown pattern type {}key)r?   setstrpattern
isinstancer   rH   rU   namerO   r_   addget_allowed_methodsappend	ExceptionrE   rF   r   get_api_endpointsurl_patternsrV   rW   extendformattypesortedr	   )r>   r?   rc   rV   rW   rd   api_endpointsri   rI   r$   rU   rX   methodendpointnested_endpointss                  r+   rp   z$EndpointEnumerator.get_api_endpointss   s    }}H$ # &	PG#goo"66J':.N33J?D&//H&||H33hB	R  $33D(C  #44$)--d3&*&>&>x&H ;F(,fh'?H)00:; G[1#'#9#9$11% )1'2B2BC ))  *3G4E4EF **&7 $: 
$  $$%568??WNOM&	PP }2CD+ ! NNN#=NMNs   AF')=F'' G
Gc                 0    t        j                  dd|      S )zzUnescape all backslash escapes from `s`.

        :param str s: string with backslash escapes
        :rtype: str
        z\\(.)z\1)resub)r>   ss     r+   unescapezEndpointEnumerator.unescape   s     vvhq))r7   c                    d}|r|t         j                  |      }|s|| j                  |      z  }	 |S || j                  |d|j                                z  }||j	                         z  }||j                         d }|r||S )a  Remove backslashes escapes from all path components outside {parameters}.
        This is needed because ``simplify_regex`` does not handle this correctly.

        **NOTE:** this might destructively affect some url regex patterns that contain
        metacharacters (e.g. \w, \d) outside path parameter groups; if you are in this
        category, God help you

        :param str path: path possibly containing
        :return: the unescaped path
        :rtype: str
        ra   N)PATH_PARAMETER_REsearchr~   startgroupend)r>   r$   
clean_pathmatchs       r+   rG   z EndpointEnumerator.unescape_path   s     
%,,T2EdmmD11

 	 $--_u{{}(=>>J%++-'J		&D  r7   )NNN)ra   ra   N)Nra   NNN)__name__
__module____qualname__r<   rH   rO   r_   rp   r~   rG   __classcell__)rA   s   @r+   r   r   7   s?    
 CG&8 >@*r7   r   c                       e Zd ZdZeZeZddddddZdd	Z	e
d
        Zd Zd ZddZddZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)OpenAPISchemaGeneratorz
    This class iterates over all registered API endpoints and returns an appropriate
    OpenAPI 2.0 compliant schema. Method implementations shamelessly stolen and adapted
    from rest-framework ``SchemaGenerator``.
    r2   r/   r0   r3   r1   )getpostputpatchdeleteNc                    t        |j                  ||j                  dd      ||      | _        || _        || _        g | _        g | _        t        j                  | _
        | t        j                  t        j                  }|rqt        j                  |      }|j                  dvs|j                  st!        d      |j"                  rt$        j'                  d|z         y|| j                  _        yy)aI  

        :param openapi.Info info: information about the API
        :param str version: API version string; if omitted, `info.default_version` will
            be used
        :param str url: API scheme, host and port; if ``None`` is passed and
            ``DEFAULT_API_URL`` is not set, the url will be inferred from the request
            made against the schema view, so you should generally not need to set this
            parameter explicitly; if the empty string is passed, no host and scheme will
            be emitted

            If `url` is not ``None`` or the empty string, it must be a scheme-absolute
            uri (i.e. starting with http:// or https://), and any path component is
            ignored;

            See also:
            :ref:`documentation on base URL construction <custom-spec-base-url>`
        :param patterns: if given, only these patterns will be enumerated for inclusion
            in the API spec
        :param urlconf: if patterns is not given, use this urlconf to enumerate
            patterns; if not given, the default urlconf is used
        descriptionra   N)httphttpsz%`url` must be an absolute HTTP(S) urlzKpath component of api base URL %s is ignored; use FORCE_SCRIPT_NAME instead)r   titler   _genr]   rK   consumesproducesr   SCHEMA_COERCE_METHOD_NAMEScoerce_method_namesr   DEFAULT_API_URLurlparseschemenetlocr   r$   rE   rF   url)r>   r]   rK   r   r?   r@   
parsed_urls          r+   r<   zOpenAPISchemaGenerator.__init__   s    . $JJTXXmR8(G
	 	#/#J#J ;+;;G"22C!**3/J  (99ARAR,-TUU0256
 !$		 r7   c                 .    | j                   j                  S r:   )r   r   )r>   s    r+   r   zOpenAPISchemaGenerator.url  s    yy}}r7   c                 V    t         j                  }|t        j                  |i       }|S )a  Get the security schemes for this API. This determines what is usable in
        security requirements, and helps clients configure their authorization
        credentials.

        :return: the security schemes usable with this API
        :rtype: dict[str,dict] or None
        )r   SECURITY_DEFINITIONSr   	_as_odict)r>   security_definitionss     r+   get_security_definitionsz/OpenAPISchemaGenerator.get_security_definitions  s0      0DD+#.#8#89Mr#R ##r7   c                     t         j                  }||D cg c]  }|g i }}|D cg c]  }t        j                  |i        }}t	        |t
              }|S c c}w c c}w )av  Get the base (global) security requirements of the API. This is never called
        if :meth:`.get_security_definitions` returns `None`.

        :param security_definitions: security definitions as returned by
            :meth:`.get_security_definitions`
        :return: the security schemes accepted by default
        :rtype: list[dict[str,list[str]]] or None
        re   )r   SECURITY_REQUIREMENTSr   r   ru   r.   )r>   r   security_requirementssecurity_schemesrs        r+   get_security_requirementsz0OpenAPISchemaGenerator.get_security_requirements*  s     !1 F F (=Q%*9"%%! %
 5J!
.0K!!"b)!
 !
 !''<$ G$$%!
s
   AAc                 H   | j                  |      }| j                  t        j                  d      }t	        t
        j                        | _        t        t
        j                        | _
        | j                  ||||      \  }}| j                         }|r| j                  |      }nd}| j                  }	|	||j                         }	t        j                   d| j"                  || j                  xs d| j                  xs d|||	|| j$                  d	t'        |      S )a  Generate a :class:`.Swagger` object representing the API schema.

        :param request: the request used for filtering accessible endpoints and finding
            the spec URI
        :type request: rest_framework.request.Request or None
        :param bool public: if True, all endpoints are included regardless of access
            through `request`

        :return: the generated Swagger specification
        :rtype: openapi.Swagger
        T)
force_initN)	r]   r#   r   r   r   security_url_prefix_versionr4   )get_endpointsreference_resolver_classr   SCHEMA_DEFINITIONSr   r   DEFAULT_PARSER_CLASSESr   r   DEFAULT_RENDERER_CLASSESr   	get_pathsr   r   r   build_absolute_uriSwaggerr]   rK   dict)
r>   r=   public	endpoints
componentsr#   rc   r   r   r   s
             r+   
get_schemaz!OpenAPISchemaGenerator.get_schema?  s    &&w/	22&&4 3 

 %\%H%HI$\%J%JKy*gvNv#<<>$($B$BCW$X!$(!hh;7.,,.C 
]]*d]]*d!5*\\
 :
 	
r7   c                     | j                   j                  |||      }t        |dd      }|?|j                         D ],  \  }}t        ||d      }|t	        |j
                  d|       . t	        |dd       |S )aP  Create a view instance from a view callback as registered in urlpatterns.

        :param callback: view callback registered in urlpatterns
        :param str method: HTTP method
        :param request: request to bind to the view
        :type request: rest_framework.request.Request or None
        :return: the view instance
        _swagger_auto_schemaNswagger_fake_viewT)r   create_viewrP   itemssetattr__func__)r>   rU   rw   r=   view	overrides_view_methods           r+   r   z"OpenAPISchemaGenerator.create_viewj  s     yy$$Xvw?H&<dC	  '__. U	%dFD9*K002H)TU
 	)40r7   c                     d|vr|S t        t        |      dd      }|rt        |      }nd}|j                  dd|z        S )aS  Coerce {pk} path arguments into the name of the model field, where possible.
        This is cleaner for an external representation (i.e. "this is an identifier",
        not "this is a database primary key").

        :param str path: the path
        :param rest_framework.views.APIView view: associated view
        :rtype: str
        z{pk}modelNidr[   )rP   r   r
   r^   )r>   r$   r   r   
field_names        r+   coerce_pathz"OpenAPISchemaGenerator.coerce_path  sM     K.t4gtD$U+JJ||FFZ$788r7   c                    | j                  | j                  j                  | j                  j                  |      }|j	                         }t        t              }i }|D ]P  \  }}}| j                  |||      }	| j                  ||	      }||   j                  ||	f       |j                  ||<   R |j                         D 
ci c]  \  }}
|||   |
f c}
}S c c}
}w )a  Iterate over all the registered endpoints in the API and return a fake view
        with the right parameters.

        :param request: request to bind to the endpoint views
        :type request: rest_framework.request.Request or None
        :return: {path: (view_class, list[(http_method, view_instance)])
        :rtype: dict[str,(type,list[(str,rest_framework.views.APIView)])]
        )r=   )endpoint_enumerator_classr   r?   r@   rp   r   r.   r   r   rn   rQ   r   )r>   r=   
enumeratorr   
view_pathsview_clsr$   rw   rU   r   methodss              r+   r   z$OpenAPISchemaGenerator.get_endpoints  s     33II		 1 17 4 

 002	 &
&/ 	*"D&(##Hfg>D##D$/Dt##VTN3%\\HTN		*
 FPEUEUEWXMD'x~w//XXXs   Cc                 J   t        |d      r|j                  }n-t        |||      rd}n| j                  |j	                            }|j                  d      j                  d      D cg c]  }d|vr|
 }}t        |      ru|j                  D ch c]	  }|dk7  r| }}t        |      dkD  r@| j                  j	                            }|| j                  v r| j                  |   }||gz   S |dd |gz   S || j                  v r| j                  |   }||gz   S c c}w c c}w )	aX  Return a list of keys that should be used to group an operation within the specification. ::

          /users/                   ("users", "list"), ("users", "create")
          /users/{pk}/              ("users", "read"), ("users", "update"), ("users", "delete")
          /users/enabled/           ("users", "enabled")  # custom viewset list action
          /users/{pk}/star/         ("users", "star")     # custom viewset detail action
          /users/{pk}/groups/       ("users", "groups", "list"), ("users", "groups", "create")
          /users/{pk}/groups/{pk}/  ("users", "groups", "read"), ("users", "groups", "update")

        :param str subpath: path to the operation with any common prefix/base path removed
        :param str method: HTTP method
        :param view: the view associated with the operation
        :rtype: list[str]
        r5   r.   r   {headr   N)hasattrr5   r   default_mappinglowerr   r   r6   
action_maplenr   )r>   subpathrw   r   r5   	componentnamed_path_componentsmapped_methodss           r+   get_operation_keysz)OpenAPISchemaGenerator.get_operation_keys  sN    4"[[F GVT2--flln= %]]3/55c:!
)# !
 !
 F#
 #oo V# N  >"Q&--flln=T555!55f=F,x77,Sb1VH<<T-----f5F %x//5!
s   )DD c                    g }|D ]q  }|j                  d      j                  d      }g }|D ]  }d|v r n|j                  |        dj                  |dd       }|s y|j                  d|z   dz          s t	        |      S )a  
        Given a list of all paths, return the common prefix which should be
        discounted when generating a schema structure.

        This will be the longest common string that does not include that last
        component of the URL, or the last component before a path parameter.

        For example: ::

            /api/v1/users/
            /api/v1/users/{pk}/

        The path prefix is ``/api/v1/``.

        :param list[str] paths: list of paths
        :rtype: str
        r   r   Nr   )r   r   rn   r"   r,   )r>   r#   prefixesr$   r   initial_componentsr   rc   s           r+   determine_path_prefixz,OpenAPISchemaGenerator.determine_path_prefix  s    $  	0DC..s3J!#' 5	)#")))45 XX0"56F OOC&L3./	0 8$$r7   c                 D    |xs | j                   j                  |||      S )a  Check if a given endpoint should be included in the resulting schema.

        :param str path: request path
        :param str method: http request method
        :param view: instantiated view callback
        :param bool public: if True, all endpoints are included regardless of access
            through `request`
        :returns: true if the view should be excluded
        :rtype: bool
        )r   has_view_permissions)r>   r$   rw   r   r   s        r+   rO   z.OpenAPISchemaGenerator.should_include_endpoint  s"     K77fdKKr7   c                 .    t        j                  |      S )zConstruct the Swagger Paths object.

        :param OrderedDict[str,openapi.PathItem] paths: mapping of paths to
            :class:`.PathItem` objects
        :returns: the :class:`.Paths` object
        :rtype: openapi.Paths
        r#   )r   Paths)r>   r#   s     r+   get_paths_objectz'OpenAPISchemaGenerator.get_paths_object  s     }}5))r7   c           
      :   |st        j                  i       dfS | j                  t        |j	                                     xs d}d|vsJ d       t               }t        |j                               D ]  \  }\  }}	i }
|	D ]F  \  }}| j                  ||||      s| j                  ||||||      }|4||
|j                         <   H |
sY|t        |      d }|j                  d      sd|z   }| j                  |||
      ||<    | j                  |      |fS )aC  Generate the Swagger Paths for the API from the given endpoints.

        :param dict endpoints: endpoints as returned by get_endpoints
        :param ReferenceResolver components: resolver/container for Swagger References
        :param Request request: the request made against the schema view; can be None
        :param bool public: if True, all endpoints are included regardless of access
            through `request`
        :returns: the :class:`.Paths` object and the longest common path prefix, as a
            2-tuple
        :rtype: tuple[openapi.Paths,str]
        r   ra   r   z,base path cannot be templated in swagger 2.0Nr   )r   r   r   r.   keysr   ru   r   rO   get_operationr   r   
startswithget_path_itemr   )r>   r   r   r=   r   rc   r#   r$   r   r   
operationsrw   r   	operationpath_suffixs                  r+   r   z OpenAPISchemaGenerator.get_paths  sB    ==r*B..++D1A,BCIr& P"PP )/	0A)B 	T%D%8WJ ' ;33D&$O ..$
G	 (1:Jv||~.;  #3v;=1"--c2"%"3K%)%7%7h
%Sk"'	T* $$U+V33r7   c           	         | j                  |t        |      d ||      }| j                  ||      }t        j                  }	t        |d|	      }	|j                  d|	      }	|	y |	|||||||      }
|
j                  |      }|yd|v r-t        |j                        t        | j                        k(  r|`	d|v r-t        |j                        t        | j                        k(  r|`
|S )a  Get an :class:`.Operation` for the given API endpoint (path, method). This
        method delegates to :meth:`~.inspectors.ViewInspector.get_operation` of a
        :class:`~.inspectors.ViewInspector` determined according to settings and
        :func:`@swagger_auto_schema <.swagger_auto_schema>` overrides.

        :param view: the view associated with this endpoint
        :param str path: the path component of the operation URL
        :param str prefix: common path prefix among all endpoints
        :param str method: the http method of the operation
        :param openapi.ReferenceResolver components: referenceable components
        :param Request request: the request made against the schema view; can be None
        :rtype: openapi.Operation
        NrN   auto_schemar   r   )r   r   get_overridesr   DEFAULT_AUTO_SCHEMA_CLASSrP   r   r   rg   r   r   )r>   r   r$   rc   rw   r   r=   operation_keysr   view_inspector_clsview_inspectorr   s               r+   r   z$OpenAPISchemaGenerator.get_operationB  s     00c&km1DfdS&&tV4	 .GG$T+;=OP&]]=:LM%+$
GY
 #00@	"s9+=+='>#dmmBT'T""s9+=+='>#dmmBT'T"r7   c                 T    | j                  ||      }t        j                  dd|i|S )a  Get a :class:`.PathItem` object that describes the parameters and operations
        related to a single path in the API.

        :param str path: the path
        :param type view_cls: the view that was bound to this path in urlpatterns
        :param dict[str,openapi.Operation] operations: operations defined on this path,
            keyed by lowercase HTTP method
        :rtype: openapi.PathItem
        
parametersr4   )get_path_parametersr   PathItem)r>   r$   r   r   path_parameterss        r+   r   z$OpenAPISchemaGenerator.get_path_itemk  s/     224BI?IjIIr7   c                     |j                         }t        |d|      }t        ||d      }t        |di       }||v r||   }t        j                  |      S )a.  Get overrides specified for a given operation.

        :param view: the view associated with the operation
        :param str method: HTTP method
        :return: a dictionary containing any overrides set by
            :func:`@swagger_auto_schema <.swagger_auto_schema>`
        :rtype: dict
        r5   Nr   )r   rP   copydeepcopy)r>   r   rw   r5   action_methodr   s         r+   r   z$OpenAPISchemaGenerator.get_overridesx  s[     x0fd3M+A2F	Y!&)I}}Y''r7   c           	      4   g }t        |      }t        j                  |      D ]  }t        ||      \  }}t	        |      xs dt
        j                  i}t        |dd      |k(  r6|d   t
        j                  k(  r t        |d|j                  dd            |d<   |rt        |dd      r|j                  }	n|rt        |dd      rt        ||      }	nd}	t        j                  d|t        |	      d	t
        j                  d
|}
|j                  |
        |S )a$  Return a list of Parameter instances corresponding to any templated path
        variables.

        :param str path: templated request path
        :param type view_cls: the view class associated with the path
        :return: path parameters
        :rtype: list[openapi.Parameter]
        rt   lookup_fieldNlookup_value_regexri   	help_textFprimary_keyT)rk   r   requiredin_r4   )r   uritemplate	variablesr   r   r   TYPE_STRINGrP   r   r
  r   	Parameterr   IN_PATHrn   )r>   r$   r   r   querysetvariabler   model_fieldattrsr   fields              r+   r   z*OpenAPISchemaGenerator.get_path_parameters  s#    
)(3#--d3 	%H!3Hh!GE;'4UATAT8UE.$78C&MW%8%88#*2EIIi4N$i  w{KG)33mU!K0D"%% *;7OO	
 E e$3	%6 r7   )ra   NNN)NFr:   )r   r   r   __doc__r   r   r   r   r   r<   propertyr   r   r   r   r   r   r   r   r   rO   r   r   r   r   r   r   r4   r7   r+   r   r      s     !30 !O-$^  $%*)
V,9&Y.30j %DL*(4T'RJ($'r7   r   )3r  loggingr{   urllib.parseparser   collectionsr   r   r  django.urlsr   r   rest_frameworkr   !rest_framework.schemas.generatorsr   _EndpointEnumeratorr	   r
   rest_framework.schemas.openapir   rest_framework.schemas.utilsr   rest_framework.settingsr   ra   r   app_settingsr   errorsr   inspectors.fieldr   r   r   r   r   utilsr   r   r   r   	getLoggerr   rE   compiler   r,   r6   r   r4   r7   r+   <module>r+     s      	  0  / % W L : ; 0  * * 
 4 K K			8	$BJJ67 	"\, \~[ [r7   