
    +}&iX                        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j                  e      Zd ZddZ G d d	      Z G d
 de      Z G d de      Z G d de      Z G d de      Z G d de      Zy)    N)serializers   )openapi)force_real_strget_field_defaultget_object_classesis_list_viewc                     t        | |      }t        j                  |      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)cls_or_instancemethod_namemethodr   s       P/usr/local/footviz/venv/lib/python3.12/site-packages/drf_yasg/inspectors/base.pyis_callable_methodr      sV    _k2FGFJ$Et|&:T:L      c                     t        | |      r	 t        | |      \  }}|r |       S 	 |rt        | |      rt        | |      S |S # t        $ r/ t        j	                  dt        |       j                  |d       Y Sw xY w)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.%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   fallback_attrdefaultview_methodis_callabales         r   call_view_methodr%      s     t[!	(:4(M%K"}$  }5t]++N  	NN% T
##  	s   A 5A;:A;c                   ,    e Zd Zd Zd ZddZd Zd Zy)BaseInspectorc                 J    || _         || _        || _        || _        || _        y)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+   s         r   __init__zBaseInspector.__init__B   s'     		$r   c                     |S )a  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,   resultr   objkwargss        r   process_resultzBaseInspector.process_resultQ   s	    $ r   Nc                    |xs i }g }|D ]  }t        j                  |      sJ d       t        |t              sJ d        || j                  | j
                  | j                  | j                  | j                  fi |}|j                  |       t        ||d      }| ||fi |}	|	t        us n t        j                  d|||       d}	t        |      D ]  } |j                  |	||fi |}	 |	S )ar  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   reversedr3   )
r,   
inspectorsr   r1   
initkwargsr2   tried_inspectors	inspectorr   r0   s
             r   probe_inspectorszBaseInspector.probe_inspectorse   s.     %2
# 	I??9- :- i7 87 "				 I ##I.YT:F~C*6*FZ'/	2 NNR	 F!"23 	RI-Y--fk3Q&QF	R r   c                 D    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]]
        get_renderersrenderer_classesr   r%   r    r,   s    r   get_renderer_classesz"BaseInspector.get_renderer_classes   s$     "TYY9KRP
 	
r   c                 D    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]]
        get_parsersparser_classesrB   rC   s    r   get_parser_classesz BaseInspector.get_parser_classes   s$     "TYY7GL
 	
r   N)r   
__module____qualname__r-   r3   r>   rD   rH   r/   r   r   r'   r'   A   s    (3j

r   r'   c                       e Zd ZdZd Zd Zy)PaginatorInspectorzBase inspector for paginators.

    Responsible for determining extra query parameters and response structure added by
    given paginators.
    c                     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]
        r8   )r,   	paginators     r   get_paginator_parametersz+PaginatorInspector.get_paginator_parameters   
     r   c                     t         S )al  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
        rO   )r,   rP   response_schemas      r   get_paginated_responsez)PaginatorInspector.get_paginated_response   s
     r   N)r   rJ   rK   __doc__rQ   rU   r/   r   r   rM   rM      s    	
r   rM   c                       e Zd ZdZd Zy)FilterInspectorzBase inspector for filter backends.

    Responsible for determining extra query parameters added by given filter backends.
    c                     t         S )a6  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]
        rO   )r,   filter_backends     r   get_filter_parametersz%FilterInspector.get_filter_parameters   rR   r   N)r   rJ   rK   rV   r[   r/   r   r   rX   rX      s    
	r   rX   c                   :     e Zd ZdZ fdZd Zd Zd Zd Z xZ	S )FieldInspectorz5Base inspector for serializers and serializer fields.c                 B    t         t        |   |||||       || _        y rI   )superr]   r-   field_inspectors)r,   r    r)   r   r*   r+   r`   	__class__s          r   r-   zFieldInspector.__init__   s"    nd,T4WU 0r   c                     t        |dd      }t        |di       }|r&|j                         D ]  \  }}t        |||        yy)a^  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
        MetaNswagger_schema_fields)r   itemssetattr)r,   serializer_or_fieldschemametard   attrvals          r   add_manual_fieldsz FieldInspector.add_manual_fields   sS     *FD9 '.Er J 288: +	cc*+ !r   c                     t         S )a1  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
        rO   r,   fieldswagger_object_typeuse_referencesr2   s        r   field_to_swagger_objectz&FieldInspector.field_to_swagger_object   s
    & r   c                 `     | j                   | j                  d|d| j                  if||d|S )a  Helper 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
        rr   r`   )rp   rq   r>   r`   rn   s        r   probe_field_inspectorsz%FieldInspector.probe_field_inspectors
  sM     %t$$!!%!6!67	

 !4)
 
 	
r   c                    	 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(  r	nd	t        dd      }|rt        |      ndt         j                  k7  rndd 	fd	}t         j                  k(  rt         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_textc                    d|vr"t         j                  k(  rj                  |d<   d|vr7t         j                  k7  r$t	              }|d t
        j                  fvr||d<   |r5|j                  dd       t         j                  k7  r|j                  d       |j                  d       t        dd       rd|d<   |j                  	       | ?t        |       sJ t        |j                               D ]  \  }}t        | ||        | }n d	i |}t         j                   k(  r
j#                  |       |S )
Nrequiredr"   r   titledescription
allow_nullT
x_nullabler/   )r   	Parameterry   Itemsr   r   emptyget
TYPE_ARRAY
setdefaultr   updater   sortedre   rf   Schemarl   )existing_objectuse_field_titleinstance_kwargsr"   keyrk   r0   r{   ro   r2   r,   rp   rz   s          r   SwaggerTypez6FieldInspector._get_partial_types.<locals>.SwaggerTypeO  sG   /1'7+<+<<.3nn
+ 0'7==8+E24):):";;18OI.  #''59K9KK**7E:&**=+FulD104-""6**!/3FGGG &'<'<'> ? 7HCOS#67(,?? #gnn4&&uf5Mr   )NT)	r   r   r~   r   r   SwaggerDictlabelr   r   )
r,   ro   rp   rq   r2   rw   r   child_swagger_typer{   rz   s
   ``` `   @@r   _get_partial_typesz!FieldInspector._get_partial_types  s    D #w~~w7H7H'--&XXXXeW%8%89 	
:	
9 05{{u{{+(GNN:E 	 E;5	3<nY/$.'--?KT 	(	 (	Z 2W^^CGNN 	 ...r   )
r   rJ   rK   rV   r-   rl   rr   ru   r   __classcell__ra   s   @r   r]   r]      s     ?1+*
*_/r   r]   c                       e Zd Zd Zd Zy)SerializerInspectorc                     t         S )a5  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
        rO   r,   
serializers     r   
get_schemazSerializerInspector.get_schema  rR   r   c                     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]
        rO   r,   r   in_s      r   get_request_parametersz*SerializerInspector.get_request_parameters  s
     r   N)r   rJ   rK   r   r   r/   r   r   r   r     s    	r   r   c                   x     e Zd ZdZdZdZg Zg Zg Z fdZ	d Z
d Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zd Z xZS )ViewInspector)PUTPATCHPOSTDELETE)r   r   r   )GETc                     t         t        |   |||||       || _        | j	                  d       | j	                  d       | j	                  d       y)a   
        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>`
        r`   filter_inspectorspaginator_inspectorsN)r_   r   r-   	overrides_prepend_inspector_overrides)r,   r    r)   r   r*   r+   r   ra   s          r   r-   zViewInspector.__init__  sP     	mT+D$
GT"))*<=))*=>))*@Ar   c                     | j                   j                  |d       }|r.t        | |      D cg c]  }||vr|
 }}t        | |||z          y y c c}w rI   )r   r   r   rf   )r,   r:   extra_inspectorsinspdefault_inspectorss        r   r   z*ViewInspector._prepend_inspector_overrides  sk    >>--j$? $D*5"// " "
 D*&69K&KL "s   Ac                     t        d      )a  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()!)NotImplementedError)r,   operation_keyss     r   get_operationzViewInspector.get_operation  s     ""QRRr   c                 X    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    rC   s    r   r	   zViewInspector.is_list_view  s     DIIt{{DII>>r   c                 r    | j                         xr& | j                  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_methodsrC   s    r   has_list_responsezViewInspector.has_list_response  s5       " 
KK4#F#FF	
r   c                 T    t        | j                  dd      xr | j                         S )zwDetermine whether filter backend parameters should be included for this
        request.

        :rtype: bool
        filter_backendsNr   r    r   rC   s    r   should_filterzViewInspector.should_filter  s&     tyy"3T:Wt?U?U?WWr   c                     | j                         sg S g }t        | j                  d      D ]+  }|| j                  | j                  d |             xs g z  }- |S )zqReturn the parameters added to the view by its filter backends.

        :rtype: list[openapi.Parameter]
        r   r[   )r   r   r    r>   r   )r,   fieldsrZ   s      r   r[   z#ViewInspector.get_filter_parameters  so    
 !!#I%dii1BC 	N%%**,C^EU  	F	 r   c                 T    t        | j                  dd      xr | j                         S )zDetermine whether paging parameters and structure should be added to this
        operation's request and response.

        :rtype: bool
        rP   Nr   rC   s    r   should_pagezViewInspector.should_page  s%     tyy+t4Q9O9O9QQr   c                     | j                         sg S | j                  | j                  dt        | j                  d            xs g S )zkReturn the parameters added to the view by its paginator.

        :rtype: list[openapi.Parameter]
        rQ   rP   )r   r>   r   r   r    rC   s    r   get_pagination_parametersz'ViewInspector.get_pagination_parameters  sN    
 !I !!))*		;/ 
 	
r   c                 V    | j                  | 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
        r   r`   rt   r   s     r   serializer_to_schemaz"ViewInspector.serializer_to_schema  s4     $$!!!6!67	
 	
r   c                 b    | j                  | j                  d|d| j                  i|      xs g S )a4  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]
        r   r`   )r   rt   r   s      r   serializer_to_parametersz&ViewInspector.serializer_to_parameters.  sF     !!%%(#T%:%:; "   		
r   c                 h    | j                  | j                  dt        | j                  d      |      S )a7  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
        rU   rP   )rT   )r>   r   r   r    )r,   rT   s     r   rU   z$ViewInspector.get_paginated_responseA  s9     $$%%$DII{++	 % 
 	
r   )r   rJ   rK   body_methodsimplicit_body_methodsr   r`   r   r   r-   r   r   r	   r   r   r[   r   r   r   r   rU   r   r   s   @r   r   r     so    L 5 &." BM	S?	
X&R
"

&
r   r   )NN)r   loggingrest_frameworkr    r   utilsr   r   r   r	   objectr8   	getLoggerr   r   r   r%   r'   rM   rX   r]   r   r   r/   r   r   <module>r      s      &  W W X
			8	$
!Hk
 k
\ >m $^/] ^/B. 4s
M s
r   