o
    Þhüf  ã                   @   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/html/premium_crap/venv/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||r�d||jf n|j|rŒd||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 )zßConstruct 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    

 