
    Vwgf                     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 d dlmZ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"m#Z#m$Z$ d
dlm%Z%m&Z& d
dl'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)SchemaGenerator)EndpointEnumerator)endpoint_orderingget_pk_name)get_pk_descriptionis_list_view)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_producesz{(?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           J/var/www/horilla/myenv/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                   P     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__/   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_regex3   s@    s#NNbdno!!%(:D"UV`"abbr7   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_endpoint8   s    'FtXV$,,	48"8<<1CTJ'J7GIgIg,h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_versionG   s     #8<<1CTJ'J7GIeIe,fdllIt<G '(8/9 U & 6 ,KK#+<<}!F G||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_endpoints\   s    }}H$ #  	PG#goo"66J':.N33J?D&//H&||H33D(HNPRT]Tcacemn#33D(C  #44$)--d3&*&>&>x&H ;F(,fh'?H)00:; G[1#'#9#9$11%GO'2B2BCU\UeUeJSG4E4EFY`YjYj&7 $: $  $$%568??WNOA 	PD }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

 	 $--^ekkm(<==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	   .   s(    c
*1f*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)a  

        :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    " $DJJTXXmR5PRZ\cd		#/#J#J ;+;;G"22C!**3/J  (99ARAR,-TUUlorrs #		 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 )aj  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   sm     !1 F F (Rf$gor%:$g!$gI^ _2!6!6r2!> _ _ &'<$ G$$	 %h _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273M3MZ^2_
$\%H%HI$\%J%JKy*gvNv#<<>$($B$BCW$X!$(!hh;7.,,.C 
%$--2G4RVR_R_Rgcg!5@Uft||
 @DJ?O
 	
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_view&  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 )aK  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_endpointsM  s     33DII4F4F		HYHYcj3k
002	 &
&/ 	*"D&(##Hfg>D##D$/Dt##VTN3%\\HTN		*
 FPEUEUEWXMD'x~w//XXXs   Cc                 L   t        |d      r|j                  }n-t        |||      rd}n| j                  |j	                            }|j                  d      j                  d      D cg c]  }d|vr|
 }}t        |      rv|j                  D ch c]
  }|dk7  s	| }}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_keysa  sH    4"[[F GVT2--flln= }}S!'',!
#)# !
 !
 F# &*__!&8HN  >"Q&--flln=T555!55f=F,x77,Sb1VH<<T-----f5F %x//1!
s   )D
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 )a+  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  s>    ==r*B..++D1A,BCIr& P"PP )/	0A)B 	T%D%8WJ ' ;33D&$O ..tT66:W^_	(1:Jv||~.;  #3v;<0"--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_operation  s     00c&kl1CVTR&&tV4	 .GG$T+;=OP&]]=:LM%+D$
GU^`no"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_item  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_overrides"  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_parameters3  s     
)(3#--d3 	%H!3Hh!GE;'4UATAT8UEx6(BuV}X_XkXkGk#*85I599U^`dKe#fi w{KG)33mU!K0D"%% *;7OO	
 E e$)	%, 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"$H  $% 
@*9$Y(10f %D
L*#4J$L
J("!r7   r   )3r  loggingr{   urllib.parseparser   collectionsr   r   r  django.urlsr   r   rest_frameworkr   rest_framework.schemas.openapir   !rest_framework.schemas.generatorsr	   _EndpointEnumeratorr
   r   rest_framework.schemas.utilsr   r   rest_framework.settingsr   ra   r   app_settingsr   errorsr   inspectors.fieldr   r   r   r   r   utilsr   r   r   	getLoggerr   rE   compiler   r,   r6   r   r4   r7   r+   <module>r+     s      	  0  / % : W L I 0  * * ] ] 3 = =			8	$BJJ67 	", Dd dr7   