U
    ǽb                     @   s  d dl Z d dlZd dlZd dlZd dlZ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 d	d
lmZ d	dlmZ d	dlmZmZmZmZmZ ddlm Z m!Z!m"Z"m#Z# e$e%Z&G dd de"Z'G dd de'Z(dd Z)dd Z*dYddZ+dd Z,dd Z-G dd de Z.dd  Z/ej0ej1ej2fZ3ej4e3d!ej5fej6e3d"ej7fej8ej9d#ej5fej:ej9d$ej7fej8ej;ej<fd%ej5fej:ej;ej<fd&ej7fgZ=d'd( Z>d)d* Z?ej@ejAdffejBejCejDffejEejFdffejGejFdffejHejCejIffejJejCejKffej2e?ejLffejMejAdffej1ejNdffej0ejAdffejOejCejPffejQejCejRffejSejCejTffejUejCdffejVejCdffejWejCejXffej9ejCdffgZYejPejRd+ZZej[ejCej\ffejSejCejTffej]ejCej^ffejOejCd,d- ffejWejCejXffej_ejCdffej9ejCdffejEejFdffejGejFdffej0ejAdffej1ejNdffej2e?ejLffejMejNdffejJejCejKffejHejCejIffej`ejCdffgZaeaeY Zbd.d/ Zcd0d1 Zdd2d3 Zed4d5 ZfegejFdffehejAdffeiejCdffejejNdffekejldffe	edejLffejmejCejXffe j ejCejIffe jnejCejKffg	Zoeped6rejqZrnd7d8 Zrd9d: Zseotejuejvfesf d;d< Zwd=d> ZxG d?d@ d@e ZyG dAdB dBe ZzG dCdD dDe Z{G dEdF dFe Z|G dGdH dHe Z}G dIdJ dJe Z~G dKdL dLe ZG dMdN dNe Zz d dOlmZ d dPlmZmZ W n& ek
r~   d ZZdQdR ZY nX G dSdT dTe Zzd dUlmZ W n& ek
r   G dVdW dWe ZY nX G dXdW dWe ZdS )Z    N)OrderedDict)Decimal)	signature)
validators)models)serializers)api_settings   )openapi)SwaggerGenerationError)decimal_as_floatfield_value_to_representationfilter_noneget_serializer_classget_serializer_ref_name   )FieldInspector
NotHandledSerializerInspectorcall_view_methodc                   @   sT   e Zd ZdZ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 )InlineSerializerInspectorzVProvides serializer conversions using :meth:`.FieldInspector.field_to_swagger_object`.Fc                 C   s   |  |tj| jS N)probe_field_inspectorsr
   Schemause_definitionsself
serializer r   =/tmp/pip-unpacked-wheel-o6yr43pd/drf_yasg/inspectors/field.py
get_schema    s    z$InlineSerializerInspector.get_schemac                 C   s   |S )a  Add/replace parameters from the given list of automatically generated request parameters. This method
        is called only when the serializer is converted into a list of parameters for use in a form data request.

        :param serializer: serializer instance
        :param list[openapi.Parameter] parameters: genereated parameters
        :return: modified parameters
        :rtype: list[openapi.Parameter]
        r   )r   r   
parametersr   r   r   add_manual_parameters#   s    	z/InlineSerializerInspector.add_manual_parametersc                    s0   t |di } fdd| D }||S )Nfieldsc              	      s:   g | ]2\}}t |d dsj|tjj| dqS )	read_onlyF)namein_)getattrr   r
   	Parameterr   get_parameter_name).0keyvaluer&   r   r   r   
<listcomp>0   s      zDInlineSerializerInspector.get_request_parameters.<locals>.<listcomp>)r'   itemsr"   )r   r   r&   r#   r!   r   r-   r   get_request_parameters.   s
    
z0InlineSerializerInspector.get_request_parametersc                 C   s   |S r   r   r   
field_namer   r   r   get_property_name<   s    z+InlineSerializerInspector.get_property_namec                 C   s   |S r   r   r1   r   r   r   r)   ?   s    z,InlineSerializerInspector.get_parameter_namec                 C   s   t |S r   )r   r   r   r   r   r   B   s    z1InlineSerializerInspector.get_serializer_ref_namec                 C   s   t |dd }t|dS )NMetaref_name)r'   hasattr)r   r   serializer_metar   r   r   _has_ref_nameE   s    z'InlineSerializerInspector._has_ref_namec                    s0  j ||f|\ t|tjtjfrZ|j }t|pBi }f tj	|d|S t|tj
r,|tjkrtd|j |}|f fdd	}|rs| S jtj}	|	||}
|
  t|
dd }t|}|r ||kr |o|}|s td||f t|	|S tS )Ntyper/   z(cannot instantiate nested serializer as c                    s   t  }g }| j D ]b\}}|}dt|jp4d i}t|}j| f|}|||< |jrt	|dds|
| qdtj||pd d}t|dt|  |S )Nr$   F)Zuse_field_titler:   
propertiesrequired_NP_serializer)r   r#   r/   r3   boolr$   r   r   r<   r'   appendr
   TYPE_OBJECTsetattrr   )r   r;   r<   Zproperty_namechildZprop_kwargschild_schemaresultChildSwaggerTypeSwaggerTyper   use_referencesr   r   make_schema_definitionZ   s4    
   	zQInlineSerializerInspector.field_to_swagger_object.<locals>.make_schema_definitionr=   zSchema for %s would override distinct serializer %s because they implicitly share the same ref_name; explicitly set the ref_name attribute on both serializers' Meta classes)_get_partial_types
isinstancer   ListSerializer	ListFieldr   rB   find_limitsr
   
TYPE_ARRAY
Serializerr   r   __name__r   
components
with_scopeSCHEMA_DEFINITIONS
setdefaultZ_remove_read_onlyr'   r   r8   	SchemaRefr   )r   fieldswagger_object_typerH   kwargsrC   limitsr5   rI   definitionsZactual_schemaZactual_serializerZthis_serializerZexplicit_refsr   rE   r   field_to_swagger_objectI   s@    

z1InlineSerializerInspector.field_to_swagger_objectN)rQ   
__module____qualname____doc__r   r    r"   r0   r3   r)   r   r8   r\   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdS )ReferencingSerializerInspectorTN)rQ   r]   r^   r   r   r   r   r   r`      s   r`   c                 C   s   t | dd}t||}||fS )a  Try to get information about a model and model field from a queryset.

    :param queryset: the queryset
    :param field_name: target field name
    :returns: the model and target field from the queryset as a 2-tuple; both elements can be ``None``
    :rtype: tuple
    modelN)r'   get_model_field)querysetr2   ra   model_fieldr   r   r   get_queryset_field   s    
re   c                 C   s@   z$|dkr| j jW S | j |W S W n tk
r:   Y dS X dS )zTry to get the given field from a django db model.

    :param model: the model
    :param field_name: target field name
    :return: model field or ``None``
    pkN)Z_metarf   	get_field	Exception)ra   r2   r   r   r   rb      s    
rb   c                 C   sV   z:t | dd}|dk	r6|dk	r6t|t | ddks6t|W S  tk
rP   Y dS X dS )zTry to get the queryset of the given view

    :param view: the view instance or class
    :param serializer: if given, will check that the view's get_serializer_class return matches this serialzier
    :return: queryset or ``None``
    Zget_querysetrc   Nr   Zserializer_class)r   r:   AssertionErrorrh   )viewr   rc   r   r   r   get_queryset_from_view   s    rk   c                 C   s$   | dk	r t | tjr| S | j} q dS )zqGet the nearest parent ``Serializer`` instance for the given field.

    :return: ``Serializer`` or ``None``
    N)rK   r   rP   parentrW   r   r   r   get_parent_serializer   s
    rn   c                 C   sX   z<t | |}z|jjW W S  tk
r8   |jjj Y W S X W n tk
rR   Y dS X dS )zTry to find the other side of a model relationship given the name of a related field.

    :param model: one side of the relationship
    :param str source: related field name
    :return: related model or ``None``
    N)r'   relZrelated_modelrh   rW   Zremote_fieldra   )ra   sourceZ
descriptorr   r   r   get_related_model   s    
rq   c                   @   s   e Zd ZdZdd ZdS )RelatedFieldInspectorz-Provides conversions for ``RelatedField``\ s.c                 K   s  | j |||f|\}}t|tjrB| |j||}|tj|ddS t|tjsRt	S t
|dd }t|tjtjfr`t
|ddr| j|j||f|}	||	dS t
|dd}
|d k	rt||
\}}nt|}t
|d	d }t
|d
d }|st| j|}t
|d
d }t
|ddp|j}|s.t|jtjr.|jj}t||}t||
}t|pTdtji}|f |S t|tjr~|tjtjdS |tjdS )NT)r:   r/   Zunique_itemsrc   pk_field )Zexisting_objectZ
slug_fieldrf   r4   ra   rp   r:   )r:   formatr:   )rJ   rK   r   ZManyRelatedFieldr   Zchild_relationr
   rO   ZRelatedFieldr   r'   ZPrimaryKeyRelatedFieldZSlugRelatedFieldrs   re   rn   rk   rj   r2   rl   rq   rb   get_basic_type_infoTYPE_STRINGZHyperlinkedRelatedField
FORMAT_URI)r   rW   rX   rH   rY   rG   rF   rC   Zfield_querysetrD   Ztarget_fieldra   rd   Zparent_serializerr7   Z
this_modelZview_querysetrp   attrsr   r   r   r\      sD    



z-RelatedFieldInspector.field_to_swagger_objectNrQ   r]   r^   r_   r\   r   r   r   r   rr      s   rr   c                 C   s   d}| j D ]:}t|t jr
t|t js
|t jkr2q
|dk	r@ dS |}q
ztt|dddd}W n, tk
r   tjdt	|  dd Y dS X |r|
ds|
dr|dd	 d
 }|S )zGiven a ``Field``, look for a ``RegexValidator`` and try to extract its pattern and return it as a string.

    :param serializers.Field regex_field: the field instance
    :return: the extracted pattern, or ``None``
    :rtype: str
    Nregexpatternz%failed to compile regex validator of T)exc_infoz\Zz\z$)r   rK   ZRegexValidatorZURLValidatorZvalidate_ipv4_addressr'   rh   loggerwarningstrendswith)Zregex_fieldZregex_validator	validatorr}   r   r   r   
find_regex  s"    
r   Zminimummaximum
min_length
max_lengthZ	min_itemsZ	max_itemsc                    s   i } fddt D }t tjr.t s.|S  jD ]h}t|dsDq4|j}t|trdt rdt	|}|D ]2\}}}t||rh||ks|||| rh|||< qhq4t drƈ j
s|dddk rd|d< tt| S )zGiven a ``Field``, look for min/max value/length validators and return appropriate limit validation attributes.

    :param serializers.Field field: the field instance
    :return: the extracted limits
    :rtype: OrderedDict
    c                    s(   g | ] \}}}}t  |r|||fqS r   )rK   )r*   r   field_classattrimprovesrm   r   r   r.   V  s   

zfind_limits.<locals>.<listcomp>limit_valueallow_blankr   r   r   )limit_validatorsrK   r   DecimalFieldr   r   r6   r   r   floatr   getr   sortedr/   )rW   rZ   Zapplicable_limitsr   r   Zvalidator_classr   r   r   rm   r   rN   N  s(    



rN   c                 C   s   t | rtjS tjS r   )r   r
   TYPE_NUMBERrx   rm   r   r   r   decimal_field_types  s    r   )Zipv4Zipv6c                 C   s   t | jd S r   )	ip_formatr   protocolrm   r   r   r   <lambda>      r   c                 C   s   | dkrdS t D ]>\}}t| |r|\}}t|r:|| }t|rJ|| } qTqdS d}|tjkrjt| }t| }td|fd|fd|fg}|| t	|}|S )a?  Given a serializer or model ``Field``, return its basic type information - ``type``, ``format``, ``pattern``,
    and any applicable min/max limit values.

    :param field: the field instance
    :return: the extracted attributes as a dictionary, or ``None`` if the field type is not known
    :rtype: OrderedDict
    Nr:   ru   r}   )
basic_type_inforK   callabler
   rx   r   rN   r   updater   )rW   r   Ztype_formatswagger_typeru   r}   rZ   rD   r   r   r   rw     s.    


rw   c                   C   s   t jrtjS tjS r   )rest_framework_settingsZCOERCE_DECIMAL_TO_STRINGr
   rx   r   r   r   r   r   decimal_return_type  s    r   c                 C   s   t | dd p| S )N
__origin__r'   )
hint_classr   r   r   get_origin_type  s    r   c                 C   s   t | }t|ot||S r   )r   inspectisclass
issubclass)r   check_classorigin_typer   r   r   hint_class_issubclass  s    r   get_argsc                 C   s   t | ddS )N__args__r   r   )tpr   r   r   typing_get_args  s    r   c                 C   sH   t | }|r|d nt}t|p(dtji}tdtjfdtjf |fgS )Nr   r:   r/   )r   r   get_basic_type_info_from_hintr
   rx   r   rO   Items)r   argsZchild_classZchild_type_infor   r   r   inspect_collection_hint_class  s    r   c                 C   s   t | }|tjkr| jS d S r   )r   typingUnionr   )r   r   r   r   r   _get_union_types  s    
r   c                 C   s   t | }|rFt|dkrBtd|d rBt|d }|r>d|d< |S dS tD ]T\}}t| |rJt|rp||   S |\}}t|r| }td|fd|fg  S qJdS )	a[  Given a class (eg from a SerializerMethodField's return type hint,
    return its basic type information - ``type``, ``format``, ``pattern``,
    and any applicable min/max limit values.

    :param hint_class: the class
    :return: the extracted attributes as a dictionary, or ``None`` if the field type is not known
    :rtype: OrderedDict
    r	   Nr   r   Tz
x-nullabler:   ru   )r   lenrK   r   hinting_type_infor   r   r   )r   Zunion_typesrD   r   infor   ru   r   r   r   r      s(    	
r   c                   @   s   e Zd ZdZdd ZdS )SerializerMethodFieldInspectorzProvides conversion for SerializerMethodField, optionally using information from the swagger_serializer_method
    decorator.
    c                 K   s<  t |tjstS t|j|j}|d kr*tS t|dd }|r|j}|d krTt|dd }|d krb|j}|j	}|d kr|t|dd }t
|r||dd}	|jf |	}n||_||_	d|_| j|||ddS t|j}
t
|
st|
dr|
jd }
t
|
r8t|
t
js8t|
}|d k	r8| j|||f|\}}|f |S tS )	N_swagger_serializer	help_textlabelT)r   r   r$   )r$   r   r   )rK   r   ZSerializerMethodFieldr   r'   rl   method_namer   r_   r   r   r   r   r$   r   inspect_signaturereturn_annotationr6   r   r   _emptyr   rJ   )r   rW   rX   rH   rY   methodr   descriptionr   Zserializer_kwargsr   	type_inforG   rF   r   r   r   r\   ,  sL    




z6SerializerMethodFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r   '  s   r   c                   @   s   e Zd ZdZdd ZdS )SimpleFieldInspectorzProvides conversions for fields which can be described using just ``type``, ``format``, ``pattern``
    and min/max validators.
    c                 K   s4   t |}|d krtS | j|||f|\}}|f |S r   )rw   r   rJ   )r   rW   rX   rH   rY   r   rG   rF   r   r   r   r\   j  s
    z,SimpleFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r   e  s   r   c                   @   s   e Zd ZdZdd ZdS )ChoiceFieldInspectorzEProvides conversions for ``ChoiceField`` and ``MultipleChoiceField``.c                 K   sx  | j |||f|\}}t|tjrttj}g }|j D ]6}	t|tjrZt	||	gd }	n
t	||	}	|
|	 q8t|}
t|
tjrtt|
dd}t||jp|jj}t|dd r|j}|rt|}|r|d|}n>dd |D }t|dkrttt|}|r|d|}t|tjrd|tj|||d	d
}|tjkrp|d tjtjfkrpd|_n|||d	}|S tS )Nr   r4   ra   
base_fieldr:   c                 S   s   h | ]}t |qS r   rv   )r*   vr   r   r   	<setcomp>  s     z?ChoiceFieldInspector.field_to_swagger_object.<locals>.<setcomp>r   )r:   enumr9   inZmulti)rJ   rK   r   ZChoiceFieldr
   rx   choiceskeysZMultipleChoiceFieldr   r?   rn   ZModelSerializerr'   rb   rp   rl   r   rw   r   r   r   nextiterrO   r(   IN_FORMZIN_QUERYZcollection_formatr   )r   rW   rX   rH   rY   rG   rF   Z	enum_typeZenum_valueschoicer   ra   rd   Z
model_typeZenum_value_typesZvalues_typerD   r   r   r   r\   v  sL    
z,ChoiceFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r   s  s   r   c                   @   s   e Zd ZdZdd ZdS )FileFieldInspectorz*Provides conversions for ``FileField``\ s.c           
      K   s   | j |||f|\}}t|tjrtd}|tjkr\|tjdd}t|dt	j
rXtj|_|S |tjkr|tjd}	|	d tjkr||	S |tS )NzFFileField is supported only in a formData Parameter or response SchemaT)r:   r$   Zuse_urlrv   r   )rJ   rK   r   Z	FileFieldr   r
   r   rx   r'   r   ZUPLOADED_FILES_USE_URLry   ru   r(   Z	TYPE_FILEr   r   )
r   rW   rX   rH   rY   rG   rF   errrD   paramr   r   r   r\     s    

z*FileFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )DictFieldInspectorz&Provides conversion for ``DictField``.c                 K   sN   | j |||f|\}}t|tjrJ|tjkrJ| |j||}|tj|dS t	S )N)r:   Zadditional_properties)
rJ   rK   r   Z	DictFieldr
   r   r   rB   r@   r   )r   rW   rX   rH   rY   rG   rF   rC   r   r   r   r\     s    z*DictFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )HiddenFieldInspectorzHide ``HiddenField``.c                 K   s   t |tjrd S tS r   )rK   r   ZHiddenFieldr   )r   rW   rX   rH   rY   r   r   r   r\     s    z,HiddenFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )JSONFieldInspectorz&Provides conversion for ``JSONField``.c                 K   s<   | j |||f|\}}t|tjr8|tjkr8|tjdS tS Nrv   )rJ   rK   r   Z	JSONFieldr
   r   r@   r   r   rW   rX   rH   rY   rG   rF   r   r   r   r\     s    z*JSONFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r     s   r   c                   @   s   e Zd ZdZdd ZdS )StringDefaultFieldInspectorzRFor otherwise unhandled fields, return them as plain :data:`.TYPE_STRING` objects.c                 K   s"   | j |||f|\}}|tjdS r   )rJ   r
   rx   r   r   r   r   r\     s    z3StringDefaultFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r     s   r   )CamelCaseJSONParser)CamelCaseJSONRenderercamelizec                 C   s   | S r   r   )datar   r   r   r     s    r   c                   @   sB   e Zd ZdZdd Zdd Zdd Zer6er6dd	 Z	nd
d	 Z	dS )CamelCaseJSONFilterzSConverts property names to camelCase if ``djangorestframework_camel_case`` is used.c                 C   s   t tt|diS )zHack to force ``djangorestframework_camel_case`` to camelize a plain string.

        :param str s: the string
        :return: camelized string
        :rtype: str
        rt   )r   r   r   )r   sr   r   r   camelize_string  s    z#CamelCaseJSONFilter.camelize_stringc                    sP   t |di rLt fdd|j D |_t |dg rL fdd|jD |_dS )zRecursively camelize property names for the given schema using ``djangorestframework_camel_case``.
        The target schema object must be modified in-place.

        :param openapi.Schema schema: the :class:`.Schema` object
        r;   c                 3   s4   | ],\}}  | t| jp(|fV  qd S r   )r   camelize_schemar
   resolve_refrR   )r*   r+   valr   r   r   	<genexpr>  s   z6CamelCaseJSONFilter.camelize_schema.<locals>.<genexpr>r<   c                    s   g | ]}  |qS r   )r   )r*   pr   r   r   r.     s     z7CamelCaseJSONFilter.camelize_schema.<locals>.<listcomp>N)r'   r   r;   r/   r<   )r   schemar   r   r   r     s    
z#CamelCaseJSONFilter.camelize_schemac                 K   s2   t |tjjr.|  r.t|| j}| | |S r   )rK   r
   r   ZOR_REFis_camel_caser   rR   r   )r   rD   r   objrY   r   r   r   r   process_result  s    
z"CamelCaseJSONFilter.process_resultc                 C   s,   t dd |  D p*t dd |  D S )Nc                 s   s   | ]}t |tV  qd S r   )r   r   )r*   parserr   r   r   r   %  s     z4CamelCaseJSONFilter.is_camel_case.<locals>.<genexpr>c                 s   s   | ]}t |tV  qd S r   )r   r   )r*   Zrendererr   r   r   r   &  s     )anyZget_parser_classesZget_renderer_classesr   r   r   r   r   #  s    z!CamelCaseJSONFilter.is_camel_casec                 C   s   dS )NFr   r   r   r   r   r   )  s    N)
rQ   r]   r^   r_   r   r   r   r   r   r   r   r   r   r   r      s   	
r   )RecursiveFieldc                   @   s   e Zd ZdZdS )RecursiveFieldInspectorbProvides conversion for RecursiveField (https://github.com/heywbj/django-rest-framework-recursive)N)rQ   r]   r^   r_   r   r   r   r   r   0  s   r   c                   @   s   e Zd ZdZdd ZdS )r   r   c           	      K   s   t |tr|tjkr|dks$td|j}t |jtjr>|j}t	|}|d k	sbtdt
t| | jtj}tj||dd}t |jtjrtjtj|d}|S tS )NTzECan not create schema for RecursiveField when use_references is Falsez.Can't create RecursiveField schema for inline )Zignore_unresolvedr9   )rK   r   r
   r   ri   proxiedr   rL   rB   r   r   r:   rR   rS   rT   rV   r   rO   r   )	r   rW   rX   rH   rY   r   r5   r[   refr   r   r   r\   7  s    z/RecursiveFieldInspector.field_to_swagger_objectNr{   r   r   r   r   r   4  s   )N)datetimer   loggingoperatorr   uuidcollectionsr   decimalr   r   r   Zdjango.corer   Z	django.dbr   Zrest_frameworkr   Zrest_framework.settingsr   r   rt   r
   errorsr   utilsr   r   r   r   r   baser   r   r   r   	getLoggerrQ   r   r   r`   re   rb   rk   rn   rq   rr   r   ZIntegerFieldZ
FloatFieldr   Znumeric_fieldsZMinValueValidator__gt__ZMaxValueValidator__lt__ZMinLengthValidatorZ	CharFieldZMaxLengthValidatorrM   rL   r   rN   r   Z	AutoFieldZTYPE_INTEGERZBinaryFieldrx   ZFORMAT_BINARYZBooleanFieldZTYPE_BOOLEANZNullBooleanFieldZDateTimeFieldZFORMAT_DATETIMEZ	DateFieldZFORMAT_DATEZFORMAT_DECIMALZDurationFieldr   ZIPAddressFieldZFORMAT_IPV4ZGenericIPAddressFieldZFORMAT_IPV6Z	SlugFieldZFORMAT_SLUGZ	TextFieldZ	TimeFieldZ	UUIDFieldZFORMAT_UUIDZmodel_field_to_basic_typer   Z
EmailFieldZFORMAT_EMAILZURLFieldry   Z
RegexFieldZ
ModelFieldZserializer_field_to_basic_typer   rw   r   r   r   r>   intr   r   dictr@   UUIDdater   r6   r   r   r   r?   SequenceAbstractSetr   r   r   r   r   r   r   r   r   r   Z%djangorestframework_camel_case.parserr   Z%djangorestframework_camel_case.renderr   r   ImportErrorr   Zrest_framework_recursive.fieldsr   r   r   r   r   r   <module>   s   
t
:#%&'>9
	-