a
    Šxdp\  ã                   @   s,  d dl Z d dlZd dlZd dlmZmZ d dl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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( e )e*¡Z+e ,d¡Z-G dd„ deƒZG dd„ de.ƒZ/dS )é    N)ÚOrderedDictÚdefaultdict)Úurlparse)Ú
URLPatternÚURLResolver)Ú
versioning)ÚSchemaGenerator)ÚEndpointEnumerator)Úendpoint_orderingÚget_pk_name)Ú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_producesz{(?P<parameter>\w+)}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Úurlconfr   ©Ú	__class__© úK/var/www/html/Ranjet/env/lib/python3.9/site-packages/drf_yasg/generators.pyr      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_pathr   r	   Úget_path_from_regex)r   Ú
path_regexr!   r#   r$   r*   !   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 rtdS dS )NFÚversionÚversioning_classú:Úswagger_schemaT)r   r	   Úshould_include_endpointÚgetattrr   ÚclsÚ
issubclassr   ZNamespaceVersioningÚsplitÚobject)r   ÚpathÚcallbackÚapp_nameÚ	namespaceÚurl_namer-   r.   r!   r#   r$   r1   &   s    z*EndpointEnumerator.should_include_endpointc                 C   sv   t |jddƒ}|durrt|tjƒrrt | jddƒ}|rrt |ddƒ}d| }||vrft 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
        r.   Nr-   Úversion_paramú{%s}z9view %s uses URLPathVersioning but URL %s has no param %s)	r2   r3   r4   r   ZURLPathVersioningr   r'   ÚinfoÚreplace)r   r7   r8   r.   r-   r<   r#   r#   r$   Úreplace_version5   s    
ÿz"EndpointEnumerator.replace_versionc              	   C   s`  |du r| j }g }|du r tƒ }|D ](}|t|jƒ }t|tƒràzz|  |¡}	|j}
|j}|  	|	|
|phd|pnd|¡rº|  
|	|
¡}	|	|v rŒW q$| |	¡ |  |
¡D ]}|	||
f}| |¡ q W n  tyÜ   tjddd Y n0 q$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.
        Nr,   zfailed to enumerate viewT)Úexc_infoz%s:%s)r   Úprefixr9   r:   Úignored_endpointszunknown pattern type {}©Úkey)r   ÚsetÚstrÚpatternÚ
isinstancer   r*   r8   Únamer1   r@   ÚaddZget_allowed_methodsÚappendÚ	Exceptionr'   r(   r   Úget_api_endpointsZurl_patternsr9   r:   ÚextendÚformatÚtypeÚsortedr
   )r   r   rB   r9   r:   rC   Zapi_endpointsrH   r+   r7   r8   r;   ÚmethodZendpointZnested_endpointsr#   r#   r$   rN   J   sD    




û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   sb   d}|r^t  |¡}|s&||  |¡7 }q^||  |d| ¡ … ¡7 }|| ¡ 7 }|| ¡ d… }q|S )aÔ  Remove backslashe 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
        r,   N)ÚPATH_PARAMETER_REÚsearchrW   ÚstartÚgroupÚend)r   r7   Z
clean_pathÚmatchr#   r#   r$   r)   †   s    
z EndpointEnumerator.unescape_path)NNN)r,   r,   N)Nr,   NNN)Ú__name__Ú
__module__Ú__qualname__r   r*   r1   r@   rN   rW   r)   Ú__classcell__r#   r#   r!   r$   r	      s   
3	r	   c                   @   sª   e Zd ZdZeZe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 )*Ú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``.
    r,   Nc                 C   sŠ   t |j|| dd¡||ƒ| _|| _|| _g | _g | _|du rLtj	durLtj	}|r†t
 
|¡}|jdvsj|jsrtdƒ‚|jr†t d| ¡ 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
        Údescriptionr,   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   ÚtitleÚgetÚ_genr>   r-   ÚconsumesÚproducesr   ZDEFAULT_API_URLr   ÚschemeÚnetlocr   r7   r'   r(   )r   r>   r-   Úurlr   r    Ú
parsed_urlr#   r#   r$   r   ¦   s    
zOpenAPISchemaGenerator.__init__c                 C   s   | j jS r   )rh   rm   )r   r#   r#   r$   rm   Ç   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   Z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#   )Ú.0Zsecurity_schemer#   r#   r$   Ú
<listcomp>â   ó    zDOpenAPISchemaGenerator.get_security_requirements.<locals>.<listcomp>c                 S   s   g | ]}t  |i ¡‘qS r#   )r   ro   )rr   Úsrr#   r#   r$   rs   ä   rt   rD   )r   ZSECURITY_REQUIREMENTSrR   Úlist)r   rp   Ú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f | j|| jp”d| j
pœ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)Z
force_initN)	r>   Úpathsri   rj   rp   ÚsecurityÚ_urlÚ_prefixÚ_version)Úget_endpointsÚreference_resolver_classr   ZSCHEMA_DEFINITIONSr   r   ZDEFAULT_PARSER_CLASSESri   r   ZDEFAULT_RENDERER_CLASSESrj   Ú	get_pathsrq   rx   rm   Zbuild_absolute_uriZSwaggerr>   r-   Údict)
r   r   ÚpublicÚ	endpointsÚ
componentsry   rB   rp   rw   rm   r#   r#   r$   Ú
get_schemaè   s&    

ýýz!OpenAPISchemaGenerator.get_schemac                 C   sh   | j  |||¡}t|ddƒ}|durX| ¡ 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_schemaNZswagger_fake_viewT)rh   Úcreate_viewr2   ÚitemsÚsetattrÚ__func__)r   r8   rS   r   ÚviewÚ	overridesÚ_Z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Úidr=   )r2   r   r   r?   )r   r7   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
ˆ |< q0‡ 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)])]
        )r   c                    s   i | ]\}}|ˆ | |f“qS r#   r#   )rr   r7   Úmethods©Úview_clsr#   r$   Ú
<dictcomp>A  rt   z8OpenAPISchemaGenerator.get_endpoints.<locals>.<dictcomp>)Úendpoint_enumerator_classrh   r   r    rN   r   rv   r‡   r‘   rL   r3   rˆ   )	r   r   Z
enumeratorrƒ   Z
view_pathsr7   rS   r8   r‹   r#   r“   r$   r~   /  s    z$OpenAPISchemaGenerator.get_endpointsc                 C   s   | j  |||¡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]
        )rh   Zget_keys)r   ÚsubpathrS   r‹   r#   r#   r$   Úget_operation_keysC  s    z)OpenAPISchemaGenerator.get_operation_keysc                 C   s   | j  |¡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
        )rh   Údetermine_path_prefix©r   ry   r#   r#   r$   r™   T  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
        )rh   Zhas_view_permissions)r   r7   rS   r‹   r‚   r#   r#   r$   r1   h  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
        ©ry   )r   ÚPathsrš   r#   r#   r$   Úget_paths_objectt  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 ]\}\}}	i }
|	D ]B\}}|  ||||¡szq`|  	||||||¡}|dur`||
| 
¡ < q`|
rL|t|ƒd… }| d¡sÊd| }|  |||
¡||< qL|  |¡|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›   r,   Ú{z,base path cannot be templated in swagger 2.0Nú/)r   rœ   r™   rv   Úkeysr   rR   rˆ   r1   Úget_operationÚlowerÚlenÚ
startswithÚget_path_itemr   )r   rƒ   r„   r   r‚   rB   ry   r7   r”   r’   Ú
operationsrS   r‹   Ú	operationZpath_suffixr#   r#   r$   r€   }  s&    

z OpenAPISchemaGenerator.get_pathsc                 C   s¾   |   |t|ƒd… ||¡}|  ||¡}tj}	t|d|	ƒ}	| d|	¡}	|	du rPdS |	|||||||ƒ}
|
 |¡}|du rzdS 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
        Nr0   Zauto_schemari   rj   )r˜   r£   Úget_overridesr   ZDEFAULT_AUTO_SCHEMA_CLASSr2   rg   r¡   rF   ri   rj   )r   r‹   r7   rB   rS   r„   r   Zoperation_keysrŒ   Zview_inspector_clsZview_inspectorr§   r#   r#   r$   r¡   ¢  s     
z$OpenAPISchemaGenerator.get_operationc                 C   s    |   ||¡}tjf 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
        Ú
parameters)Úget_path_parametersr   ZPathItem)r   r7   r”   r¦   Z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
        ÚactionNr†   )r¢   r2   ÚcopyÚdeepcopy)r   r‹   rS   r«   Zaction_methodrŒ   r#   r#   r$   r¨   Ô  s    z$OpenAPISchemaGenerator.get_overridesc                 C   sÜ   g }t |ƒ}tt |¡ƒD ]¼}t||ƒ\}}t|ƒp<dtji}t|ddƒ|krt|d tjkrtt|d| 	dd¡ƒ|d< |rŒt|ddƒrŒ|j
}	n |r¨t|ddƒr¨t||ƒ}	nd}	tjf |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]
        rQ   Zlookup_fieldNZlookup_value_regexrH   Ú	help_textFZprimary_keyT)rJ   rc   ÚrequiredZin_)r   rR   ÚuritemplateÚ	variablesr   r   r   ZTYPE_STRINGr2   rg   r®   r   Ú	Parameterr   ZIN_PATHrL   )r   r7   r”   r©   ZquerysetÚvariablerŽ   Zmodel_fieldÚattrsrc   Úfieldr#   r#   r$   rª   å  s,    üûz*OpenAPISchemaGenerator.get_path_parameters)r,   NNN)NF)N)r^   r_   r`   Ú__doc__r	   r–   r   r   r   Úpropertyrm   rq   rx   r…   r‡   r‘   r~   r˜   r™   r1   r   r€   r¡   r¥   r¨   rª   r#   r#   r#   r$   rb   ž   s*   
!

 
	%&rb   )0r¬   ÚloggingrT   Úcollectionsr   r   r°   Zcoreapi.compatr   Zdjango.urlsr   r   Zrest_frameworkr   Zrest_framework.schemasr   Z!rest_framework.schemas.generatorsr	   Z_EndpointEnumeratorr
   r   Zrest_framework.schemas.utilsr   Zrest_framework.settingsr   r,   r   Zapp_settingsr   Úerrorsr   Zinspectors.fieldr   r   r   r   r   Úutilsr   r   r   Ú	getLoggerr^   r'   ÚcompilerX   r6   rb   r#   r#   r#   r$   Ú<module>   s.   

 