o
    >hf                     @   s>  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+e,Z-e.dZ/dd Z0dd Z1G dd deZG dd dZ2dS )    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                 C   s^   dd | D }t |}t|}|}t|D ]\}}||| kr'|d | } nqdd| S )Nc                 S   s   g | ]
}| d d qS )/)stripsplit).0path r   s/var/www/vedio/testing/chatpythonscript.ninositsolution.com/env/lib/python3.10/site-packages/drf_yasg/generators.py
<listcomp>   s    zcommon_path.<locals>.<listcomp>r   )minmax	enumeratejoin)pathssplit_pathss1s2commonicr   r   r    common_path   s   r-   c                 C   s   | dvS )N>   listcreateupdatedestroyretrievepartial_updater   )actionr   r   r    is_custom_action(   s   r5   c                       sZ   e Zd Zd fdd	Z fddZd fdd	Zd	d
 ZdddZdd Zdd Z	  Z
S )r   Nc                    s   t t| || || _d S N)superr   __init__request)selfpatternsurlconfr9   	__class__r   r    r8   /   s   
zEndpointEnumerator.__init__c                    s,   | drtd| | tt| |S )N)zEurl pattern does not end in $ ('%s') - unexpected things might happen)endswithloggerwarningunescape_pathr7   r   get_path_from_regex)r:   
path_regexr=   r   r    rD   3   s   
z&EndpointEnumerator.get_path_from_regex c                    sx   t t| ||sdS t| jdd }t|jdd }|d ur.t|tjr.|r.||	dvr.dS t|jdt
 d u r:dS dS )NFversionversioning_class:swagger_schemaT)r7   r   should_include_endpointgetattrr9   cls
issubclassr   NamespaceVersioningr   object)r:   r   callbackapp_name	namespaceurl_namerG   rH   r=   r   r    rK   8   s   z*EndpointEnumerator.should_include_endpointc                 C   sv   t |jdd}|dur9t|tjr9t | jdd}|r9t |dd}d| }||vr3td|j||f  |||}|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
        rH   NrG   version_param{%s}z9view %s uses URLPathVersioning but URL %s has no param %s)	rL   rM   rN   r   URLPathVersioningr9   rA   inforeplace)r:   r   rQ   rH   rG   rU   r   r   r    replace_versionG   s   
z"EndpointEnumerator.replace_versionc              	   C   sV  |du r| j }g }|du rt }|D ]}|t|j }t|trnz=| |}	|j}
|j}| 	|	|
|p3d|p6d|r\| 
|	|
}	|	|v rEW q||	 | |
D ]}|	||
f}|| qOW q tym   tjddd Y qw t|tr| j|j||rd||jf n|j|rd||jf n|j|d}|| qtdt| qt|td	}|S )
z
        Return a list of all available API endpoints by inspecting the URL conf.

        Copied entirely from super.
        NrF   zfailed to enumerate viewT)exc_infoz%s:%s)r;   prefixrR   rS   ignored_endpointszunknown pattern type {}key)r;   setstrpattern
isinstancer   rD   rQ   namerK   rZ   addget_allowed_methodsappend	ExceptionrA   rB   r   get_api_endpointsurl_patternsrR   rS   extendformattypesortedr	   )r:   r;   r\   rR   rS   r]   api_endpointsrb   rE   r   rQ   rT   methodendpointnested_endpointsr   r   r    ri   \   sH   




z$EndpointEnumerator.get_api_endpointsc                 C   s   t dd|S )zzUnescape all backslash escapes from `s`.

        :param str s: string with backslash escapes
        :rtype: str
        z\\(.)z\1)resub)r:   sr   r   r    unescape   s   zEndpointEnumerator.unescapec                 C   sh   d}|r2t |}|s|| |7 }	 |S || |d|  7 }|| 7 }|| d }|s|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
        rF   N)PATH_PARAMETER_REsearchrv   startgroupend)r:   r   
clean_pathmatchr   r   r    rC      s   
	z EndpointEnumerator.unescape_path)NNN)rF   rF   N)NrF   NNN)__name__
__module____qualname__r8   rD   rK   rZ   ri   rv   rC   __classcell__r   r   r=   r    r   .   s    
3	r   c                   @   s   e Zd ZdZeZeZddddddZd-d
dZ	e
dd Zdd Zdd Zd.ddZd/ddZdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd	S )0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deleterF   Nc                 C   s   t |j||dd||| _|| _|| _g | _g | _tj	| _
|du r*tjdur*tj}|rOt|}|jdvs9|js=td|jrItd|  dS || j_dS dS )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
        descriptionrF   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   _genrX   rG   consumesproducesr   SCHEMA_COERCE_METHOD_NAMEScoerce_method_namesr   DEFAULT_API_URLurlparseschemenetlocr   r   rA   rB   url)r:   rX   rG   r   r;   r<   
parsed_urlr   r   r    r8      s    
zOpenAPISchemaGenerator.__init__c                 C   s   | j jS r6   )r   r   )r:   r   r   r    r      s   zOpenAPISchemaGenerator.urlc                 C   s   t j}|durt|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
        N)r   SECURITY_DEFINITIONSr   	_as_odict)r:   security_definitionsr   r   r    get_security_definitions   s   z/OpenAPISchemaGenerator.get_security_definitionsc                 C   s:   t j}|du rdd |D }dd |D }t|td}|S )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
        Nc                 S   s   g | ]}|g iqS r   r   )r   security_schemer   r   r    r!      s    zDOpenAPISchemaGenerator.get_security_requirements.<locals>.<listcomp>c                 S   s   g | ]}t |i qS r   )r   r   )r   srr   r   r    r!     s    r^   )r   SECURITY_REQUIREMENTSrn   r.   )r:   r   security_requirementsr   r   r    get_security_requirements   s   z0OpenAPISchemaGenerator.get_security_requirementsFc           
      C   s   |  |}| jtjdd}ttj| _ttj	| _
| ||||\}}|  }|r/| |}nd}| j}	|	du r@|dur@| }	tjd| j|| jpJd| j
pNd|||	|| 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)	rX   r&   r   r   r   security_url_prefix_versionr   )get_endpointsreference_resolver_classr   SCHEMA_DEFINITIONSr   r   DEFAULT_PARSER_CLASSESr   r   DEFAULT_RENDERER_CLASSESr   	get_pathsr   r   r   build_absolute_uriSwaggerrX   rG   dict)
r:   r9   public	endpoints
componentsr&   r\   r   r   r   r   r   r    
get_schema  s&   

z!OpenAPISchemaGenerator.get_schemac                 C   sh   | j |||}t|dd}|dur,| D ]\}}t||d}|dur+t|jd| q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_viewrL   itemssetattr__func__)r:   rQ   rp   r9   view	overrides_view_methodr   r   r    r   &  s   	z"OpenAPISchemaGenerator.create_viewc                 C   s>   d|vr|S t t|dd}|rt|}nd}|dd| 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idrV   )rL   r   r
   rY   )r:   r   r   r   
field_namer   r   r    coerce_path;  s   
z"OpenAPISchemaGenerator.coerce_pathc           	         s   | j | jj| jj|d}| }tt}i  |D ] \}}}| |||}| ||}|| 	||f |j
 |< q fdd| D S )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)])]
        )r9   c                    s   i | ]\}}| | |fqS r   r   )r   r   methodsview_clsr   r    
<dictcomp>_  s    z8OpenAPISchemaGenerator.get_endpoints.<locals>.<dictcomp>)endpoint_enumerator_classr   r;   r<   ri   r   r.   r   r   rg   rM   r   )	r:   r9   
enumeratorr   
view_pathsr   rp   rQ   r   r   r   r    r   M  s   z$OpenAPISchemaGenerator.get_endpointsc                 C   s   t |dr	|j}nt|||rd}n| j|  }dd |ddD }t|rWdd |jD }t	|dkrN| j|  }|| j
v rI| j
| }||g S |d	d
 |g S || j
v ra| j
| }||g S )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]
        r4   r.   c                 S   s   g | ]}d |vr|qS ){r   )r   	componentr   r   r    r!   z  s
    z=OpenAPISchemaGenerator.get_operation_keys.<locals>.<listcomp>r   c                 S   s   h | ]}|d kr|qS )headr   )r   rp   r   r   r    	<setcomp>  s    z<OpenAPISchemaGenerator.get_operation_keys.<locals>.<setcomp>r   N)hasattrr4   r   default_mappinglowerr   r   r5   
action_maplenr   )r:   subpathrp   r   r4   named_path_componentsmapped_methodsr   r   r    get_operation_keysa  s*   






z)OpenAPISchemaGenerator.get_operation_keysc                 C   sx   g }|D ]3}| dd}g }|D ]}d|v r n|| qd|dd }|s. dS |d| d  q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   rg   r%   r-   )r:   r&   prefixesr   r   initial_componentsr   r\   r   r   r    determine_path_prefix  s   z,OpenAPISchemaGenerator.determine_path_prefixc                 C   s   |p	| 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   rp   r   r   r   r   r    rK     s   
z.OpenAPISchemaGenerator.should_include_endpointc                 C   s   t j|d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&   r   r   r    get_paths_object  s   z'OpenAPISchemaGenerator.get_paths_objectc              
   C   s   |s
t ji ddfS | t| pd}d|vsJ dt }t| D ]H\}\}}	i }
|	D ]!\}}| ||||s=q0| 	||||||}|durQ||
|
 < q0|
rn|t|d }|dsed| }| |||
||< q&| ||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   rF   r   z,base path cannot be templated in swagger 2.0Nr   )r   r   r   r.   keysr   rn   r   rK   get_operationr   r   
startswithget_path_itemr   )r:   r   r   r9   r   r\   r&   r   r   r   
operationsrp   r   	operationpath_suffixr   r   r    r     s*   

z OpenAPISchemaGenerator.get_pathsc                 C   s   |  |t|d ||}| ||}tj}	t|d|	}	|d|	}	|	du r(dS |	|||||||}
|
|}|du r=dS d|v rMt|j	t| j	krM|`	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
        NrJ   auto_schemar   r   )r   r   get_overridesr   DEFAULT_AUTO_SCHEMA_CLASSrL   r   r   r`   r   r   )r:   r   r   r\   rp   r   r9   operation_keysr   view_inspector_clsview_inspectorr   r   r   r    r     s    
z$OpenAPISchemaGenerator.get_operationc                 C   s    |  ||}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
        
parametersNr   )get_path_parametersr   PathItem)r:   r   r   r   path_parametersr   r   r    r     s   	z$OpenAPISchemaGenerator.get_path_itemc                 C   sF   |  }t|d|}t||d}t|di }||v r|| }t|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
        r4   Nr   )r   rL   copydeepcopy)r:   r   rp   r4   action_methodr   r   r   r    r   "  s   
z$OpenAPISchemaGenerator.get_overridesc                 C   s   g }t |}t|D ]^}t||\}}t|pdtji}t|dd|kr8|d tjkr8t|d|dd|d< |rDt|ddrD|j	}	n|rRt|ddrRt
||}	nd}	tjd|t|	d	tjd
|}
||
 q|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]
        rm   lookup_fieldNlookup_value_regexrb   	help_textFprimary_keyT)rd   r   requiredin_r   )r   uritemplate	variablesr   r   r   TYPE_STRINGrL   r   r   r   	Parameterr   IN_PATHrg   )r:   r   r   r   querysetvariabler   model_fieldattrsr   fieldr   r   r    r   3  s,   z*OpenAPISchemaGenerator.get_path_parameters)rF   NNN)NFr6   )r~   r   r   __doc__r   r   r   r   r   r8   propertyr   r   r   r   r   r   r   r   r   rK   r   r   r   r   r   r   r   r   r   r    r      s8    
$


 3"	%&r   )3r   loggingrs   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   rF   r   app_settingsr   errorsr   inspectors.fieldr   r   r   r   r   utilsr   r   r   	getLoggerr~   rA   compilerw   r-   r5   r   r   r   r   r    <module>   s4    

 