a
    ΝGdR                     @   s   d dl Z d dlZd dlmZ ddlmZ ddlmZmZm	Z	m
Z
 e ZeeZdd Zddd	ZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )    N)serializers   )openapi)force_real_strget_field_defaultget_object_classesis_list_viewc                 C   sJ   t | |}t|r(t |dd r(|dfS ddlm} |t|| |d tfS )N__self__Tr   )getattr_static)getattrinspectismethodr
   
isinstancestaticmethod)Zcls_or_instancemethod_namemethodr
    r   T/var/www/html/django/DPS/env/lib/python3.9/site-packages/drf_yasg/inspectors/base.pyis_callable_method   s
    
r   c                 C   sn   t | |rRzt| |\}}|r&| W S W n( tyP   tjdt| jdd Y n0 |rjt | |rjt| |S |S )a  Call a view method which might throw an exception. If an exception is thrown, log an informative error message
    and return the value of fallback_attr, or default if not present. The method must be callable without any arguments
    except cls or self.

    :param view: view class or instance; if a class is passed, instance methods won't be called
    :type view: rest_framework.views.APIView or type[rest_framework.views.APIView]
    :param str method_name: name of a method on the view
    :param str fallback_attr: name of an attribute on the view to fall back on, if calling the method fails
    :param default: default value if all else fails
    :return: view method's return value, or value of view's fallback_attr, or default
    :rtype: any or None
    zview's %s raised exception during schema generation; use `getattr(self, 'swagger_fake_view', False)` to detect and short-circuit thisT)exc_info)hasattrr   	Exceptionloggerwarningtype__name__r   )viewr   Zfallback_attrdefaultZview_methodZis_callabaler   r   r   call_view_method   s    


r   c                   @   s6   e Zd Zdd Zdd ZdddZdd	 Zd
d ZdS )BaseInspectorc                 C   s"   || _ || _|| _|| _|| _dS )a  
        :param rest_framework.views.APIView view: the view associated with this endpoint
        :param str path: the path component of the operation URL
        :param str method: the http method of the operation
        :param openapi.ReferenceResolver components: referenceable components
        :param rest_framework.request.Request request: the request made against the schema view; can be None
        N)r   pathr   
componentsrequest)selfr   r    r   r!   r"   r   r   r   __init__7   s
    zBaseInspector.__init__c                 K   s   |S )ap  After an inspector handles an object (i.e. returns a value other than :data:`.NotHandled`), all inspectors
        that were probed get the chance to alter the result, in reverse order. The inspector that handled the object
        is the first to receive a ``process_result`` call with the object it just returned.

        This behavior is similar to the Django request/response middleware processing.

        If this inspector has no post-processing to do, it should just ``return result`` (the default implementation).

        :param result: the return value of the winning inspector, or ``None`` if no inspector handled the object
        :param str method_name: name of the method that was called on the inspector
        :param obj: first argument passed to inspector method
        :param kwargs: additional arguments passed to inspector method
        :return:
        r   )r#   resultr   objkwargsr   r   r   process_resultE   s    zBaseInspector.process_resultNc           
      K   s   |pi }g }|D ]}t |s&J dt|ts8J d|| j| j| j| j| jfi |}|	| t
||d}|du rzq||fi |}	|	tur qqtd||| d}	t|D ]}|j|	||fi |}	q|	S )af  Probe a list of inspectors with a given object. The first inspector in the list to return a value that
        is not :data:`.NotHandled` wins.

        :param list[type[BaseInspector]] inspectors: list of inspectors to probe
        :param str method_name: name of the target method on the inspector
        :param obj: first argument to inspector method
        :param dict initkwargs: extra kwargs for instantiating inspector class
        :param kwargs: additional arguments to inspector method
        :return: the return value of the winning inspector, or ``None`` if no inspector handled the object
        z(inspector must be a class, not an objectz&inspectors must subclass BaseInspectorNz@%s ignored because no inspector in %s handled it (operation: %s))r   isclass
issubclassr   r   r    r   r!   r"   appendr   
NotHandledr   r   reversedr(   )
r#   
inspectorsr   r&   Z
initkwargsr'   Ztried_inspectorsZ	inspectorr   r%   r   r   r   probe_inspectorsV   s(    "
zBaseInspector.probe_inspectorsc                 C   s   t t| jddg S )zGet the renderer classes of this view by calling `get_renderers`.

        :return: renderer classes
        :rtype: list[type[rest_framework.renderers.BaseRenderer]]
        Zget_renderersZrenderer_classesr   r   r   r#   r   r   r   get_renderer_classes{   s    z"BaseInspector.get_renderer_classesc                 C   s   t t| jddg S )zGet the parser classes of this view by calling `get_parsers`.

        :return: parser classes
        :rtype: list[type[rest_framework.parsers.BaseParser]]
        Zget_parsersZparser_classesr0   r1   r   r   r   get_parser_classes   s    z BaseInspector.get_parser_classes)N)r   
__module____qualname__r$   r(   r/   r2   r3   r   r   r   r   r   6   s
   
%r   c                   @   s    e Zd ZdZdd Zdd ZdS )PaginatorInspectorzBase inspector for paginators.

    Responsible for determining extra query parameters and response structure added by given paginators.
    c                 C   s   t S )a  Get the pagination parameters for a single paginator **instance**.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `paginator`.

        :param BasePagination paginator: the paginator
        :rtype: list[openapi.Parameter]
        r,   )r#   	paginatorr   r   r   get_paginator_parameters   s    z+PaginatorInspector.get_paginator_parametersc                 C   s   t S )ad  Add appropriate paging fields to a response :class:`.Schema`.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `paginator`.

        :param BasePagination paginator: the paginator
        :param openapi.Schema response_schema: the response schema that must be paged.
        :rtype: openapi.Schema
        r7   )r#   r8   response_schemar   r   r   get_paginated_response   s    	z)PaginatorInspector.get_paginated_responseN)r   r4   r5   __doc__r9   r;   r   r   r   r   r6      s   
r6   c                   @   s   e Zd ZdZdd ZdS )FilterInspectorzBase inspector for filter backends.

    Responsible for determining extra query parameters added by given filter backends.
    c                 C   s   t S )a.  Get the filter parameters for a single filter backend **instance**.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `filter_backend`.

        :param BaseFilterBackend filter_backend: the filter backend
        :rtype: list[openapi.Parameter]
        r7   )r#   filter_backendr   r   r   get_filter_parameters   s    z%FilterInspector.get_filter_parametersN)r   r4   r5   r<   r?   r   r   r   r   r=      s   r=   c                       s@   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z  Z	S )FieldInspectorz6Base inspector for serializers and serializer fields. c                    s"   t t| ||||| || _d S )N)superr@   r$   field_inspectors)r#   r   r    r   r!   r"   rB   	__class__r   r   r$      s    zFieldInspector.__init__c                 C   s>   t |dd}t |di }|r:| D ]\}}t||| q$dS )aV  Set fields from the ``swagger_schema_fields`` attribute on the Meta class. This method is called
        only for serializers or fields that are converted into ``openapi.Schema`` objects.

        :param serializer_or_field: serializer or field instance
        :param openapi.Schema schema: the schema object to be modified in-place
        ZMetaNswagger_schema_fields)r   itemssetattr)r#   Zserializer_or_fieldZschemametarE   attrvalr   r   r   add_manual_fields   s
    z FieldInspector.add_manual_fieldsc                 K   s   t S )a  Convert a drf Serializer or Field instance into a Swagger object.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `field`.

        :param rest_framework.serializers.Field field: the source field
        :param type[openapi.SwaggerDict] swagger_object_type: should be one of Schema, Parameter, Items
        :param bool use_references: if False, forces all objects to be declared inline
           instead of by referencing other components
        :param kwargs: extra attributes for constructing the object;
           if swagger_object_type is Parameter, ``name`` and ``in_`` should be provided
        :return: the swagger object
        :rtype: openapi.Parameter or openapi.Items or openapi.Schema or openapi.SchemaRef
        r7   r#   fieldswagger_object_typeuse_referencesr'   r   r   r   field_to_swagger_object   s    z&FieldInspector.field_to_swagger_objectc                 K   s&   | j | jd|d| jif||d|S )zHelper method for recursively probing `field_inspectors` to handle a given field.

        All arguments are the same as :meth:`.field_to_swagger_object`.

        :rtype: openapi.Parameter or openapi.Items or openapi.Schema or openapi.SchemaRef
        rP   rB   )rN   rO   r/   rB   rL   r   r   r   probe_field_inspectors   s    z%FieldInspector.probe_field_inspectorsc                    s   t jt jt jfv sJ tt jr,J djr<tjndt jkrNndtdd}|rjt|nd t jkr| nd d fdd	}t jkrt jnt j}||fS )a[  Helper method to extract generic information from a field and return a partial constructor for the
        appropriate openapi object.

        All arguments are the same as :meth:`.field_to_swagger_object`.

        The return value is a tuple consisting of:

        * a function for constructing objects of `swagger_object_type`; its prototype is: ::

            def SwaggerType(existing_object=None, **instance_kwargs):

          This function creates an instance of `swagger_object_type`, passing the following attributes to its init,
          in order of precedence:

            - arguments specified by the ``kwargs`` parameter of :meth:`._get_partial_types`
            - ``instance_kwargs`` passed to the constructor function
            - ``title``, ``description``, ``required``, ``x-nullable`` and ``default`` inferred from the field,
              where appropriate

          If ``existing_object`` is not ``None``, it is updated instead of creating a new object.

        * a type that should be used for child objects if `field` is of an array type. This can currently have two
          values:

            - :class:`.Schema` if `swagger_object_type` is :class:`.Schema`
            - :class:`.Items` if `swagger_object_type` is  :class:`.Parameter` or :class:`.Items`

        :rtype: (function,type[openapi.Schema] or type[openapi.Items])
        z,passed field is already a SwaggerDict objectN	help_textTc                    s  d|vrt jkrj|d< d|vrLt jkrLt}|d tjfvrL||d< |rn|dd t jkrn|	d  d ur|	d  t
dd rd|d< | | d urt| sJ t| D ]\}}t| || q| }nf i |}t jkr| |S )	Nrequiredr   r   titledescriptionZ
allow_nullTZ
x_nullable)r   	ParameterrT   Itemsr   r   emptyget
TYPE_ARRAY
setdefaultr   updater   sortedrF   rG   SchemarK   )Zexisting_objectZuse_field_titleZinstance_kwargsr   keyrJ   r%   rV   rM   r'   r#   rN   rU   r   r   SwaggerType  s,    

z6FieldInspector._get_partial_types.<locals>.SwaggerType)NT)	r   r_   rW   rX   r   ZSwaggerDictlabelr   r   )r#   rM   rN   rO   r'   rS   rb   Zchild_swagger_typer   ra   r   _get_partial_types   s    "z!FieldInspector._get_partial_types)
r   r4   r5   r<   r$   rK   rP   rR   rd   __classcell__r   r   rC   r   r@      s   r@   c                   @   s   e Zd Zdd Zdd ZdS )SerializerInspectorc                 C   s   t S )a-  Convert a DRF Serializer instance to an :class:`.openapi.Schema`.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `serializer`.

        :param serializers.BaseSerializer serializer: the ``Serializer`` instance
        :rtype: openapi.Schema
        r7   r#   
serializerr   r   r   
get_schema6  s    zSerializerInspector.get_schemac                 C   s   t S )a  Convert a DRF serializer into a list of :class:`.Parameter`\ s.

        Should return :data:`.NotHandled` if this inspector does not know how to handle the given `serializer`.

        :param serializers.BaseSerializer serializer: the ``Serializer`` instance
        :param str in_: the location of the parameters, one of the `openapi.IN_*` constants
        :rtype: list[openapi.Parameter]
        r7   r#   rh   in_r   r   r   get_request_parameters@  s    	z*SerializerInspector.get_request_parametersN)r   r4   r5   ri   rl   r   r   r   r   rf   5  s   
rf   c                       s   e Zd ZdZdZdZg Zg Zg Z f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  ZS )ViewInspector)PUTPATCHPOSTDELETE)rn   ro   rp   )GETc                    s@   t t| ||||| || _| d | d | d dS )z
        Inspector class responsible for providing :class:`.Operation` definitions given a view, path and method.

        :param dict overrides: manual overrides as passed to :func:`@swagger_auto_schema <.swagger_auto_schema>`
        rB   filter_inspectorspaginator_inspectorsN)rA   rm   r$   	overrides_prepend_inspector_overrides)r#   r   r    r   r!   r"   ru   rC   r   r   r$   Z  s
    

zViewInspector.__init__c                    s>   | j |d   r: fddt| |D }t| | |  d S )Nc                    s   g | ]}| vr|qS r   r   ).0ZinspZextra_inspectorsr   r   
<listcomp>i      z>ViewInspector._prepend_inspector_overrides.<locals>.<listcomp>)ru   rZ   r   rG   )r#   r.   Zdefault_inspectorsr   rx   r   rv   f  s    z*ViewInspector._prepend_inspector_overridesc                 C   s   t ddS )aw  Get an :class:`.Operation` for the given API endpoint (path, method).
        This includes query, body parameters and response schemas.

        :param tuple[str] operation_keys: an array of keys describing the hierarchical layout of this view in the API;
          e.g. ``('snippets', 'list')``, ``('snippets', 'retrieve')``, etc.
        :rtype: openapi.Operation
        z-ViewInspector must implement get_operation()!N)NotImplementedError)r#   Zoperation_keysr   r   r   get_operationl  s    zViewInspector.get_operationc                 C   s   t | j| j| jS )a  Determine whether this view is a list or a detail view. The difference between the two is that
        detail views depend on a pk/id path parameter. Note that a non-detail view does not necessarily imply a list
        response (:meth:`.has_list_response`), nor are list responses limited to non-detail views.

        For example, one might have a `/topic/<pk>/posts` endpoint which is a detail view that has a list response.

        :rtype: bool)r   r    r   r   r1   r   r   r   r   v  s    zViewInspector.is_list_viewc                 C   s   |   o| j | jv S )zDetermine whether this view returns multiple objects. By default this is any non-detail view
        (see :meth:`.is_list_view`) whose request method is one of :attr:`.implicit_list_response_methods`.

        :rtype: bool
        )r   r   upperimplicit_list_response_methodsr1   r   r   r   has_list_response  s    zViewInspector.has_list_responsec                 C   s   t | jddo|  S )zoDetermine whether filter backend parameters should be included for this request.

        :rtype: bool
        filter_backendsNr   r   r   r1   r   r   r   should_filter  s    zViewInspector.should_filterc                 C   s@   |   sg S g }t| jdD ]}|| | jd| p6g 7 }q|S )zqReturn the parameters added to the view by its filter backends.

        :rtype: list[openapi.Parameter]
        r   r?   )r   r   r   r/   rs   )r#   fieldsr>   r   r   r   r?     s    z#ViewInspector.get_filter_parametersc                 C   s   t | jddo|  S )zDetermine whether paging parameters and structure should be added to this operation's request and response.

        :rtype: bool
        r8   Nr   r1   r   r   r   should_page  s    zViewInspector.should_pagec                 C   s(   |   sg S | | jdt| jdp&g S )zkReturn the parameters added to the view by its paginator.

        :rtype: list[openapi.Parameter]
        r9   r8   )r   r/   rt   r   r   r1   r   r   r   get_pagination_parameters  s    

z'ViewInspector.get_pagination_parametersc                 C   s   |  | jd|d| jiS )a#  Convert a serializer to an OpenAPI :class:`.Schema`.

        :param serializers.BaseSerializer serializer: the ``Serializer`` instance
        :returns: the converted :class:`.Schema`, or ``None`` in case of an unknown serializer
        :rtype: openapi.Schema or openapi.SchemaRef
        ri   rB   rQ   rg   r   r   r   serializer_to_schema  s    z"ViewInspector.serializer_to_schemac                 C   s    | j | jd|d| ji|dpg S )a(  Convert a serializer to a possibly empty list of :class:`.Parameter`\ s.

        :param serializers.BaseSerializer serializer: the ``Serializer`` instance
        :param str in_: the location of the parameters, one of the `openapi.IN_*` constants
        :rtype: list[openapi.Parameter]
        rl   rB   )rk   rQ   rj   r   r   r   serializer_to_parameters  s    z&ViewInspector.serializer_to_parametersc                 C   s   | j | jdt| jd|dS )a+  Add appropriate paging fields to a response :class:`.Schema`.

        :param openapi.Schema response_schema: the response schema that must be paged.
        :returns: the paginated response class:`.Schema`, or ``None`` in case of an unknown pagination scheme
        :rtype: openapi.Schema
        r;   r8   )r:   )r/   rt   r   r   )r#   r:   r   r   r   r;     s    
z$ViewInspector.get_paginated_response)r   r4   r5   Zbody_methodsZimplicit_body_methodsr~   rB   rs   rt   r$   rv   r|   r   r   r   r?   r   r   r   r   r;   re   r   r   rC   r   rm   L  s$   

rm   )NN)r   loggingZrest_frameworkr    r   utilsr   r   r   r   objectr,   	getLoggerr   r   r   r   r   r6   r=   r@   rf   rm   r   r   r   r   <module>   s   


V|