U
    Ç½„b‰D  ã                   @   sª   d dl 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 dd	lmZmZmZmZmZmZmZmZmZ d
dlmZmZ e  e¡ZG dd„ deƒZdS )é    N)ÚOrderedDict©Úis_form_media_type)Ú
AutoSchema)Ú
is_successé   )Úopenapi)ÚSwaggerGenerationError)	Úfilter_noneÚforce_real_strÚforce_serializer_instanceÚget_consumesÚget_producesÚguess_response_statusÚmerge_paramsÚno_bodyÚparam_list_to_odicté   )ÚViewInspectorÚcall_view_methodc                       sä   e Zd Zd4‡ fdd„	Zd5d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d„ Zdd„ Zd d!„ Zd"d#„ Zd6d$d%„Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd7d.d/„Zd0d1„ Zd2d3„ Z‡  ZS )8ÚSwaggerAutoSchemaNc                    s4   t t| ƒ ||||||¡ tƒ | _|| j_|| _d S ©N)Úsuperr   Ú__init__r   Ú_schÚviewÚoperation_keys)Úselfr   ÚpathÚmethodÚ
componentsÚrequestÚ	overridesr   ©Ú	__class__© ú</tmp/pip-unpacked-wheel-o6yr43pd/drf_yasg/inspectors/view.pyr      s    zSwaggerAutoSchema.__init__c                 C   s¾   |p| j }|  ¡ }|  ¡ }|  |¡}|  ¡ }|| }t|ƒ}|  |¡}|  |¡}|  ¡ \}}	|  	¡ }
|
d ks~t
|
tƒs~tdƒ‚|  ¡ }|  |¡}|  ¡ }tj|t|	ƒt|ƒ||||||
|d�
S )Nz7security must be a list of security requirement objects)
Úoperation_idÚdescriptionÚsummaryÚ	responsesÚ
parametersÚconsumesÚproducesÚtagsÚsecurityÚ
deprecated)r   r   r   Úget_request_body_parametersÚget_query_parametersr
   Úadd_manual_parametersÚget_operation_idÚget_summary_and_descriptionÚget_securityÚ
isinstanceÚlistÚAssertionErrorÚis_deprecatedÚget_tagsÚget_responsesr   Z	Operationr   )r   r   r,   r-   ÚbodyÚqueryr+   r'   r)   r(   r/   r0   r.   r*   r%   r%   r&   Úget_operation   s6    




özSwaggerAutoSchema.get_operationc                 C   s„   |   ¡ }d}|dkrg S t|tjjƒr*|}tdd„ |D ƒƒrV|dk	rLtdƒ‚|  |¡S |dkrh|  |¡}|dk	r||  	|¡gS g S dS )a   Return the request body parameters for this view. |br|
        This is either:

        -  a list with a single object Parameter with a :class:`.Schema` derived from the request serializer
        -  a list of primitive Parameters parsed as form data

        :param list[str] consumes: a list of accepted MIME types as returned by :meth:`.get_consumes`
        :return: a (potentially empty) list of :class:`.Parameter`\ s either ``in: body`` or ``in: formData``
        :rtype: list[openapi.Parameter]
        Nc                 s   s   | ]}t |ƒV  qd S r   r   ©Ú.0Úencodingr%   r%   r&   Ú	<genexpr>O   s     z@SwaggerAutoSchema.get_request_body_parameters.<locals>.<genexpr>z$form request body cannot be a Schema)
Úget_request_serializerr7   r   ÚSchemaÚOR_REFÚanyr	   Úget_request_form_parametersÚget_request_body_schemaÚmake_body_parameter)r   r,   Ú
serializerÚschemar%   r%   r&   r1   <   s    

z-SwaggerAutoSchema.get_request_body_parametersc                 C   s   t | jdƒS )z¶Return the serializer as defined by the view's ``get_serializer()`` method.

        :return: the view's ``Serializer``
        :rtype: rest_framework.serializers.Serializer
        Zget_serializer)r   r   ©r   r%   r%   r&   Úget_view_serializerX   s    z%SwaggerAutoSchema.get_view_serializerc                 C   sd   | j  dd¡}|dk	r`|tkr"tS | j| jkrFtdd | j¡ d ƒ‚t|tj	j
ƒrX|S t|ƒS |S )zOParse the request_body key in the override dict. This method is not public API.Úrequest_bodyNz%request_body can only be applied to (ú,z=); are you looking for query_serializer or manual_parameters?)r"   Úgetr   r   Úbody_methodsr	   Újoinr7   r   rE   rF   r   ©r   Zbody_overrider%   r%   r&   Ú_get_request_body_override`   s    ÿz,SwaggerAutoSchema._get_request_body_overridec                 C   s4   |   ¡ }|dkr$| j| jkr$|  ¡ S |tkr0dS |S )zúReturn the request serializer (used for parsing the request payload) for this endpoint.

        :return: the request serializer, or one of :class:`.Schema`, :class:`.SchemaRef`, ``None``
        :rtype: rest_framework.serializers.Serializer
        N)rU   r   Zimplicit_body_methodsrN   r   rT   r%   r%   r&   rD   p   s    z(SwaggerAutoSchema.get_request_serializerc                 C   s   | j |tjd�S )zçGiven a Serializer, return a list of ``in: formData`` :class:`.Parameter`\ s.

        :param serializer: the view's request serializer as returned by :meth:`.get_request_serializer`
        :rtype: list[openapi.Parameter]
        ©Úin_)Úserializer_to_parametersr   ÚIN_FORM©r   rK   r%   r%   r&   rH   €   s    z-SwaggerAutoSchema.get_request_form_parametersc                 C   s
   |   |¡S )zûReturn the :class:`.Schema` for a given request's body data. Only applies to PUT, PATCH and POST requests.

        :param serializer: the view's request serializer as returned by :meth:`.get_request_serializer`
        :rtype: openapi.Schema
        )Úserializer_to_schemarZ   r%   r%   r&   rI   ˆ   s    z)SwaggerAutoSchema.get_request_body_schemac                 C   s   t jdt jd|d�S )z¶Given a :class:`.Schema` object, create an ``in: body`` :class:`.Parameter`.

        :param openapi.Schema schema: the request body schema
        :rtype: openapi.Parameter
        ÚdataT)ÚnamerW   ÚrequiredrL   )r   Ú	ParameterÚIN_BODY)r   rL   r%   r%   r&   rJ   �   s    z%SwaggerAutoSchema.make_body_parameterc                 C   s    | j  dd¡pg }tdd„ |D ƒƒr,tdƒ‚tdd„ |D ƒƒr–tdd„ |D ƒƒ}|sjtdd„ |  ¡ D ƒƒsrtd	ƒ‚| j| jkr–td
d | j¡ d ƒ‚t||ƒS )zùAdd/replace parameters from the given list of automatically generated request parameters.

        :param list[openapi.Parameter] parameters: genereated parameters
        :return: modified parameters
        :rtype: list[openapi.Parameter]
        Úmanual_parametersNc                 s   s   | ]}|j tjkV  qd S r   ©rW   r   r`   ©rA   Úparamr%   r%   r&   rC   ¡   s     z:SwaggerAutoSchema.add_manual_parameters.<locals>.<genexpr>zDspecify the body parameter as a Schema or Serializer in request_bodyc                 s   s   | ]}|j tjkV  qd S r   )rW   r   rY   rc   r%   r%   r&   rC   £   s     c                 s   s   | ]}|j tjkV  qd S r   rb   rc   r%   r%   r&   rC   ¤   s     c                 s   s   | ]}t |ƒV  qd S r   r   r@   r%   r%   r&   rC   ¥   s     z~cannot add form parameters when the request has a request body; did you forget to set an appropriate parser class on the view?z(form parameters can only be applied to (rP   z) HTTP methods)	r"   rQ   rG   r	   r   r   rR   rS   r   )r   r+   ra   Zhas_body_parameterr%   r%   r&   r3   ˜   s    
ÿÿz'SwaggerAutoSchema.add_manual_parametersc                 C   s   |   ¡ }tj|  |¡d�S )z§Get the possible responses for this view as a swagger :class:`.Responses` object.

        :return: the documented responses
        :rtype: openapi.Responses
        )r*   )Úget_response_serializersr   Z	ResponsesÚget_response_schemas)r   Úresponse_serializersr%   r%   r&   r<   ®   s    ÿzSwaggerAutoSchema.get_responsesc                 C   s    |   ¡ }|r|tk	r|S |  ¡ S )a  Return the default response serializer for this endpoint. This is derived from either the ``request_body``
        override or the request serializer (:meth:`.get_view_serializer`).

        :return: response serializer, :class:`.Schema`, :class:`.SchemaRef`, ``None``
        )rU   r   rN   rT   r%   r%   r&   Úget_default_response_serializer¹   s    z1SwaggerAutoSchema.get_default_response_serializerc                 C   sŽ   | j  ¡ }t|ƒ}d}|dkr&|  ¡ }|p,d}|rLt|tjƒsL|  |¡pJd}|r~|  ¡ rhtjtj	|d�}|  
¡ r~|  |¡p||}tt|ƒ|iƒS )z•Get the default responses determined for this view from the request serializer and request method.

        :type: dict[str, openapi.Schema]
        Ú )rQ   ÚpostÚputÚpatch)ÚtypeÚitems)r   Úlowerr   rh   r7   r   rE   r[   Zhas_list_responseÚ
TYPE_ARRAYZshould_pageZget_paginated_responser   Ústr)r   r   Zdefault_statusZdefault_schemar%   r%   r&   Úget_default_responsesÅ   s    
z'SwaggerAutoSchema.get_default_responsesc                 C   sd   | j  dd¡pi }tdd„ | ¡ D ƒƒ}tƒ }tdd„ |D ƒƒsH|  ¡ }| dd„ | ¡ D ƒ¡ |S )aØ  Return the response codes that this view is expected to return, and the serializer for each response body.
        The return value should be a dict where the keys are possible status codes, and values are either strings,
        ``Serializer``\ s, :class:`.Schema`, :class:`.SchemaRef` or :class:`.Response` objects. See
        :func:`@swagger_auto_schema <.swagger_auto_schema>` for more details.

        :return: the response serializers
        :rtype: dict
        r*   Nc                 s   s   | ]\}}t |ƒ|fV  qd S r   ©rq   ©rA   ÚscÚrespr%   r%   r&   rC   ç   s     z=SwaggerAutoSchema.get_response_serializers.<locals>.<genexpr>c                 s   s"   | ]}|d krt t|ƒƒV  qdS )ÚdefaultN)r   Úint)rA   ru   r%   r%   r&   rC   ê   s      c                 s   s   | ]\}}t |ƒ|fV  qd S r   rs   rt   r%   r%   r&   rC   í   s     )r"   rQ   r   rn   rG   rr   Úupdate)r   Zmanual_responsesr*   r%   r%   r&   re   Ý   s    	z*SwaggerAutoSchema.get_response_serializersc                 C   sÈ   t ƒ }| ¡ D ]´\}}t|tƒr2tjt|ƒd�}n„|s:qn|t|tjƒr||}t|dƒr¶t|jtj	j
ƒs¶t|jƒ}|  |¡|_n:t|tj	j
ƒrštjd|d�}nt|ƒ}tjd|  |¡d�}||t|ƒ< q|S )a7  Return the :class:`.openapi.Response` objects calculated for this view.

        :param dict response_serializers: response serializers as returned by :meth:`.get_response_serializers`
        :return: a dictionary of status code to :class:`.Response` object
        :rtype: dict[str, openapi.Response]
        )r(   rL   ri   )r(   rL   )r   rn   r7   rq   r   ÚResponser   ÚhasattrrL   rE   rF   r   r[   )r   rg   r*   ru   rK   Úresponser%   r%   r&   rf   ð   s2    
ÿ
þþz&SwaggerAutoSchema.get_response_schemasc                 C   s"   | j  dd¡}|dk	rt|ƒ}|S )z�Return the query serializer (used for parsing query parameters) for this endpoint.

        :return: the query serializer, or ``None``
        Úquery_serializerN)r"   rQ   r   )r   r}   r%   r%   r&   Úget_query_serializer  s    z&SwaggerAutoSchema.get_query_serializerc                 C   sp   |   ¡ |  ¡  }|  ¡ }g }|dk	rh| j|tjd�}ttt|ƒƒtt|ƒƒ@ ƒdkrht	d| j
| jf ƒ‚|| S )zdReturn the query parameters accepted by this view.

        :rtype: list[openapi.Parameter]
        NrV   r   zryour query_serializer contains fields that conflict with the filter_backend or paginator_class on the view - %s %s)Zget_filter_parametersZget_pagination_parametersr~   rX   r   ZIN_QUERYÚlenÚsetr   r	   r   r   )r   Znatural_parametersr}   Zserializer_parametersr%   r%   r&   r2     s     
ÿÿz&SwaggerAutoSchema.get_query_parametersc                 C   s*   |p| j }| j dd¡}|s&d |¡}|S )ap  Return an unique ID for this operation. The ID must be unique across
        all :class:`.Operation` objects in the API.

        :param tuple[str] operation_keys: an array of keys derived from the pathdescribing the hierarchical layout
            of this view in the API; e.g. ``('snippets', 'list')``, ``('snippets', 'retrieve')``, etc.
        :rtype: str
        r'   ri   Ú_)r   r"   rQ   rS   )r   r   r'   r%   r%   r&   r4   2  s
    

z"SwaggerAutoSchema.get_operation_idc                 C   sX   d}d}|  dd¡}t|ƒdkrP|d  ¡ |d< t|d ƒ|k rP|\}}| ¡ }||fS )aS  Decide if and how to split a summary out of the given description. The default implementation
        uses the first paragraph of the description as a summary if it is less than 120 characters long.

        :param description: the full description to be analyzed
        :return: summary and description
        :rtype: (str,str)
        Néx   z

r   r   r   )Úsplitr   Ústrip)r   r(   r)   Zsummary_max_lenÚsectionsr%   r%   r&   Úsplit_summary_from_descriptionA  s    	z0SwaggerAutoSchema.split_summary_from_descriptionc                 C   sl   | j  dd¡}| j  dd¡}|dkrd| j | j| j¡p8d}| ¡  dd¡}|rd|dkrd|  |¡\}}||fS )zžReturn an operation summary and description determined from the view's docstring.

        :return: summary and description
        :rtype: (str,str)
        Zoperation_descriptionNZoperation_summaryri   ú)	r"   rQ   r   Úget_descriptionr   r   r„   Úreplacer†   )r   r(   r)   r%   r%   r&   r5   U  s    z-SwaggerAutoSchema.get_summary_and_descriptionc                 C   s   | j  dd¡S )aT  Return a list of security requirements for this operation.

        Returning an empty list marks the endpoint as unauthenticated (i.e. removes all accepted
        authentication schemes). Returning ``None`` will inherit the top-level secuirty requirements.

        :return: security requirements
        :rtype: list[dict[str,list[str]]]r/   N©r"   rQ   rM   r%   r%   r&   r6   g  s    zSwaggerAutoSchema.get_securityc                 C   s   | j  dd¡S )zƒReturn ``True`` if this operation is to be marked as deprecated.

        :return: deprecation status
        :rtype: bool
        r0   NrŠ   rM   r%   r%   r&   r:   q  s    zSwaggerAutoSchema.is_deprecatedc                 C   s(   |p| j }| j d¡}|s$|d g}|S )a	  Get a list of tags for this operation. Tags determine how operations relate with each other, and in the UI
        each tag will show as a group containing the operations that use it. If not provided in overrides,
        tags will be inferred from the operation url.

        :param tuple[str] operation_keys: an array of keys derived from the pathdescribing the hierarchical layout
            of this view in the API; e.g. ``('snippets', 'list')``, ``('snippets', 'retrieve')``, etc.
        :rtype: list[str]
        r.   r   )r   r"   rQ   )r   r   r.   r%   r%   r&   r;   y  s
    	

zSwaggerAutoSchema.get_tagsc                 C   s   t |  ¡ ƒS )zTReturn the MIME types this endpoint can consume.

        :rtype: list[str]
        )r   Zget_parser_classesrM   r%   r%   r&   r   Š  s    zSwaggerAutoSchema.get_consumesc                 C   s   t |  ¡ ƒS )zTReturn the MIME types this endpoint can produce.

        :rtype: list[str]
        )r   Zget_renderer_classesrM   r%   r%   r&   r   ‘  s    zSwaggerAutoSchema.get_produces)N)N)N)N)Ú__name__Ú
__module__Ú__qualname__r   r?   r1   rN   rU   rD   rH   rI   rJ   r3   r<   rh   rr   re   rf   r~   r2   r4   r†   r5   r6   r:   r;   r   r   Ú__classcell__r%   r%   r#   r&   r      s2   
"$



r   )ÚloggingÚcollectionsr   Zrest_framework.requestr   Zrest_framework.schemasr   Zrest_framework.statusr   ri   r   Úerrorsr	   Úutilsr
   r   r   r   r   r   r   r   r   Úbaser   r   Ú	getLoggerr‹   Úloggerr   r%   r%   r%   r&   Ú<module>   s   ,
