3
Ah`s                 @   s  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mZmZmZmZmZmZmZ d dlmZ d dlmZ d d	lmZmZmZ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(m)Z) G dd de$Z*G dd de&Z+dS )    N)OrderedDict)Decimal)
attrgetter)urljoin)DecimalValidatorEmailValidatorMaxLengthValidatorMaxValueValidatorMinLengthValidatorMinValueValidatorRegexValidatorURLValidator)models)	force_str)RemovedInDRF314Warning
exceptions	renderersserializers)uritemplate)_UnvalidatedFieldempty)api_settings   )BaseSchemaGenerator)ViewInspector)get_pk_descriptionis_list_viewc               @   s&   e Zd Zdd Zdd Zd	ddZdS )
SchemaGeneratorc             C   s.   | j pd| jpdd}| jd k	r*| j|d< |S )N )titleversiondescription)r   r    r!   )selfinfo r$   M/tmp/pip-build-9m32_hle/djangorestframework/rest_framework/schemas/openapi.pyget_info   s
    

zSchemaGenerator.get_infoc          
   C   s   i }x|D ]x}xr|| D ]f}d|| | kr.q|| | d }||krpt jdj|| d || d |||d ||d||< qW q
W d S )NoperationIdzYou have a duplicated operationId in your OpenAPI schema: {operation_id}
	Route: {route1}, Method: {method1}
	Route: {route2}, Method: {method2}
	An operationId has to be unique across your schema. Your schema may not work in other tools.routemethod)Zroute1Zmethod1Zroute2Zmethod2operation_id)r(   r)   )warningswarnformat)r"   pathsidsr(   r)   r*   r$   r$   r%   check_duplicate_operation_id)   s     



z,SchemaGenerator.check_duplicate_operation_idNFc             C   s(  | j   i }i }| j|rdn|\}}x|D ]\}}}	| j|||	sFq,|	jj||}
|	jj||}x<|j D ]0}||krzql|| || krqltjdj	| qlW |j
| |jdr|dd }t| jpd|}|j|i  |
|| |j < q,W | j| d| j |d}t|dkr$d|i|d	< |S )
z,
        Generate a OpenAPI schema.
        Nz@Schema component "{}" has been overriden with a different value./r   z3.0.2)Zopenapir#   r.   r   Zschemas
components)Z_initialise_endpointsZ_get_paths_and_endpointsZhas_view_permissionsschemaget_operationget_componentskeysr+   r,   r-   update
startswithr   url
setdefaultlowerr0   r&   len)r"   requestpublicZcomponents_schemasr.   _Zview_endpointspathr)   view	operationr2   kr3   r$   r$   r%   
get_schemaC   s8    


zSchemaGenerator.get_schema)NF)__name__
__module____qualname__r&   r0   rD   r$   r$   r$   r%   r      s   r   c                   sN  e Zd ZdP fdd	Zg Zg Zddd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 d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Zd<d= Z d>d? Z!d@dA Z"dBdC Z#dDdE Z$dFdG Z%dHdI Z&dJdK Z'dLdM Z(dNdO Z)  Z*S )Q
AutoSchemaNc                s@   |r t dd |D  r td|| _|| _|| _t j  dS )a  
        :param operation_id_base: user-defined name in operationId. If empty, it will be deducted from the Model/Serializer/View name.
        :param component_name: user-defined component's name. If empty, it will be deducted from the Serializer's class name.
        c             s   s   | ]}t |tV  qd S )N)
isinstancestr).0tagr$   r$   r%   	<genexpr>~   s    z&AutoSchema.__init__.<locals>.<genexpr>z'tags must be a list or tuple of string.N)all
ValueError_tagsoperation_id_basecomponent_namesuper__init__)r"   tagsrQ   rR   )	__class__r$   r%   rT   y   s    zAutoSchema.__init__retrievecreater7   ZpartialUpdatedestroy)getpostputpatchdeletec             C   s   i }| j |||d< | j|||d< g }|| j||7 }|| j||7 }|| j||7 }||d< | j||}|rx||d< | j|||d< | j|||d< |S )Nr'   r!   
parametersZrequestBody	responsesrU   )get_operation_idget_descriptionget_path_parametersget_pagination_parametersget_filter_parametersget_request_bodyget_responsesget_tags)r"   r@   r)   rB   r_   request_bodyr$   r$   r%   r4      s    zAutoSchema.get_operationc             C   sP   | j dk	r| j S |jj}tjdtj}|jd|}|dkrLtdj|jj|S )z
        Compute the component's name from the serializer.
        Raise an exception if the serializer's class name is "Serializer" (case-insensitive).
        N
serializerr   z"{}" is an invalid class name for schema generation. Serializer's class name should be unique and explicit. e.g. "ItemSerializer")	rR   rV   rE   recompile
IGNORECASEsub	Exceptionr-   )r"   rj   rR   patternr$   r$   r%   get_component_name   s    
zAutoSchema.get_component_namec             C   sH   |j  dkri S | j||}t|tjs,i S | j|}| j|}||iS )zN
        Return components with their properties from the serializer.
        r^   )r;   get_serializerrI   r   
Serializerrq   map_serializer)r"   r@   r)   rj   rR   contentr$   r$   r%   r5      s    

zAutoSchema.get_componentsc             C   s.   |j d}|d djdd |dd  D  S )Nr?   r   r   c             s   s   | ]}|j  V  qd S )N)r   )rK   xr$   r$   r%   rM      s    z,AutoSchema._to_camel_case.<locals>.<genexpr>r   )splitjoin)r"   Z	snake_strr2   r$   r$   r%   _to_camel_case   s    
zAutoSchema._to_camel_casec             C   s   t t | jdddd}| jdk	r(| j}n|dk	r8|j}n| j||dk	rp| j||jj}|jdr|dd }nX| jjj}|jdr|dd }n|jdr|dd }|j|j r|dt|  }|d
kr|jd r|d7 }|S )za
        Compute the base part for operation ID from the model, serializer or view name.
        querysetNmodelrs   
   ZAPIView   ZView   listsii)	getattrrA   rQ   rE   rr   rV   endswithr   r<   )r"   r@   r)   actionr{   namer$   r$   r%   get_operation_id_base   s&    




z AutoSchema.get_operation_id_basec             C   s`   t | jd|j }t||| jr&d}n$|| jkr<| j|}n| j|j  }| j|||}|| S )z^
        Compute an operation ID from the view type and get_operation_id_base method.
        r   r   )r   rA   r;   r   method_mappingry   r   )r"   r@   r)   method_namer   r   r$   r$   r%   ra      s    
zAutoSchema.get_operation_idc       	      C   s   t stdtt| jdddd}g }xt j|D ]}d}|dk	ry|jj|}W n tk
rj   d}Y nX |dk	r|jrt	|j}n|dk	r|j
rt||}|dd|dd	id
}|j| q2W |S )zL
        Return a list of parameters from templated path variables.
        z;`uritemplate` must be installed for OpenAPI schema support.rz   Nr{   r   r@   Ttypestring)r   inrequiredr!   r3   )r   AssertionErrorr   rA   	variables_meta	get_fieldro   	help_textr   Zprimary_keyr   append)	r"   r@   r)   r{   r_   variabler!   model_fieldZ	parameterr$   r$   r%   rc     s*    

zAutoSchema.get_path_parametersc             C   s<   | j ||sg S g }x"| jjD ]}|| j| j7 }qW |S )N)allows_filtersrA   filter_backendsget_schema_operation_parameters)r"   r@   r)   r_   Zfilter_backendr$   r$   r%   re   ,  s    z AutoSchema.get_filter_parametersc             C   s:   t | jdddkrdS t| jdr.| jjdkS |j dkS )z
        Determine whether to include filter Fields in schema.

        Default implementation looks for ModelViewSet or GenericAPIView
        actions/methods that cause filtering on the default implementation.
        r   NFr   r   rW   r7   partial_updaterY   rZ   r\   r]   r^   )r   rW   r7   r   rY   )rZ   r\   r]   r^   )r   rA   hasattrr   r;   )r"   r@   r)   r$   r$   r%   r   4  s
    zAutoSchema.allows_filtersc             C   s0   | j }t|||sg S | j }|s&g S |j|S )N)rA   r   get_paginatorr   )r"   r@   r)   rA   	paginatorr$   r$   r%   rd   A  s    z$AutoSchema.get_pagination_parametersc             C   s   t tj|j}tdd |D r(d}nLtdd |D r@d}n4tdd |D rXd}ntdd |D rpd	}nd }d
|i}|r||d< |S )Nc             s   s   | ]}t |tV  qd S )N)rI   bool)rK   choicer$   r$   r%   rM   O  s    z-AutoSchema.map_choicefield.<locals>.<genexpr>booleanc             s   s   | ]}t |tV  qd S )N)rI   int)rK   r   r$   r$   r%   rM   Q  s    integerc             s   s   | ]}t |tttfV  qd S )N)rI   r   floatr   )rK   r   r$   r$   r%   rM   S  s    numberc             s   s   | ]}t |tV  qd S )N)rI   rJ   )rK   r   r$   r$   r%   rM   V  s    r   enumr   )r   r   fromkeyschoicesrN   )r"   fieldr   r   mappingr$   r$   r%   map_choicefieldM  s    zAutoSchema.map_choicefieldc             C   s
  t |tjrd| j|jdS t |tjr@| j|}d|d< |S t |tjr^d| j|jdS t |tj	rt
|jdd }|d k	r|jj}t |tjrddiS t |tjrd| j|dS t |tjr| j|S t |tjrdi d}t |jts| j|j|d< |S t |tjr dd	d
S t |tjr8ddd
S t |tjrPddd
S t |tjrhddd
S t |tjrddd
S t |tjrddi}|jdkr|j|d< |S t |tjrDt
|dtjrddd
}nddi}|jrt d|jd d  d |d< |j!r4t"|j!d d |d< |d  |d< | j#|| |S t |tj$rjddi}| j#|| |S t |tj%rddi}| j#|| t"|j&dddkst"|j&dddkrd|d< |S t |tj'rddd
S tj(d tj)dtj*dtj+di}d|j&|j,diS )!Narray)r   itemsobjectr   r{   r   r   r   date)r   r-   z	date-timeemailuriuuidZbothr-   coerce_to_stringdecimalr   .r   01
multipleOf9maximumminimumr   iZint64binaryr   )-rI   r   ZListSerializerrt   childrs   ZManyRelatedField	map_fieldZchild_relationZPrimaryKeyRelatedFieldr   rz   r   pkr   Z	AutoFieldZMultipleChoiceFieldr   ZChoiceField	ListFieldr   Z	DateFieldZDateTimeFieldZ
EmailFieldZURLFieldZ	UUIDFieldZIPAddressFieldprotocolZDecimalFieldr   COERCE_DECIMAL_TO_STRINGdecimal_placesr   Zmax_whole_digitsr   _map_min_maxZ
FloatFieldZIntegerFieldrZ   Z	FileFieldZBooleanFieldZ	JSONFieldZ	DictFieldZHStoreFieldrV   )r"   r   datar{   r   r   ru   ZFIELD_CLASS_SCHEMA_TYPEr$   r$   r%   r   i  s    



,
zAutoSchema.map_fieldc             C   s$   |j r|j |d< |jr |j|d< d S )Nr   r   )Z	max_valueZ	min_value)r"   r   ru   r$   r$   r%   r     s    
zAutoSchema._map_min_maxc             C   s   g }i }x|j j D ]}t|tjr&q|jr8|j|j | j|}|j	rPd|d< |j
r^d|d< |jrld|d< |jd k	r|jtkrt|j r|j|d< |jrt|j|d< | j|| |||j< qW d|d}|r||d	< |S )
NTZreadOnlyZ	writeOnlyZnullabledefaultr!   r   )r   
propertiesr   )fieldsvaluesrI   r   ZHiddenFieldr   r   
field_namer   Z	read_onlyZ
write_onlyZ
allow_nullr   r   callabler   rJ   map_field_validators)r"   rj   r   r   r   r3   resultr$   r$   r%   rt     s2    
 
zAutoSchema.map_serializerc             C   sl  xd|j D ]X}t|tr"d|d< t|tr4d|d< t|trT|jjjdd|d< q
t|tr~d}t|t	j
rrd}|j||< q
t|trd	}t|t	j
rd
}|j||< q
t|tr|j|d< q
t|tr|j|d< q
t|tot|dtj r
|jrtd|jd d  d |d< |jr
|j}|jdk	rB|jdkrB||j8 }t|d d |d< |d  |d< q
W dS )z&
        map field validators
        r   r-   r   z\Zz\zrp   Z	maxLengthZmaxItemsZ	minLengthZminItemsr   r   r   r   r   r   r   r   Nr   r   )Z
validatorsrI   r   r   r   regexrp   replacer   r   r   Zlimit_valuer
   r	   r   r   r   r   r   r   r   Z
max_digitsr   )r"   r   r3   v	attr_namedigitsr$   r$   r%   r   !  s>    








zAutoSchema.map_field_validatorsc             C   s   t | jdd }|r| S d S )Npagination_class)r   rA   )r"   r   r$   r$   r%   r   I  s    zAutoSchema.get_paginatorc             C   s   t ttd| jjS )N
media_type)r   mapr   rA   Zparser_classes)r"   r@   r)   r$   r$   r%   map_parsersO  s    zAutoSchema.map_parsersc             C   s4   g }x*| j jD ]}t|tjr q|j|j qW |S )N)rA   Zrenderer_classes
issubclassr   ZBrowsableAPIRendererr   r   )r"   r@   r)   Zmedia_typesZrendererr$   r$   r%   map_renderersR  s    zAutoSchema.map_renderersc             C   sP   | j }t|dsd S y|j S  tjk
rJ   tjdj|jj	|| d S X d S )Nrr   zt{}.get_serializer() raised an exception during schema generation. Serializer fields will not be generated for {} {}.)
rA   r   rr   r   ZAPIExceptionr+   r,   r-   rV   rE   )r"   r@   r)   rA   r$   r$   r%   rr   [  s    
zAutoSchema.get_serializerc             C   s   ddj | j|iS )Nz$refz#/components/schemas/{})r-   rq   )r"   rj   r$   r$   r%   _get_referencej  s    zAutoSchema._get_referencec                sZ   |dkri S | j ||| _| j||}t|tjs8i  n
| j| d fdd| jD iS )NPUTPATCHPOSTru   c                s   i | ]}d  i|qS )r3   r$   )rK   ct)item_schemar$   r%   
<dictcomp>{  s   z/AutoSchema.get_request_body.<locals>.<dictcomp>)r   r   r   )r   request_media_typesrr   rI   r   rs   r   )r"   r@   r)   rj   r$   )r   r%   rf   m  s    
zAutoSchema.get_request_bodyc                s   |dkrdddiiS | j ||| _| j||}t|tjs@i }n
| j|}t||| jrzd|d | j	 }|r~|j
  n| |dkrdnd	}| fd
d| jD ddiS )NDELETEZ204r!   r   r   )r   r   r   Z201Z200c                s   i | ]}d  i|qS )r3   r$   )rK   r   )response_schemar$   r%   r     s   z,AutoSchema.get_responses.<locals>.<dictcomp>)ru   r!   )r   response_media_typesrr   rI   r   rs   r   r   rA   r   Zget_paginated_response_schema)r"   r@   r)   rj   r   r   status_coder$   )r   r%   rg     s(    


zAutoSchema.get_responsesc             C   s:   | j r| j S |jdr"|dd  }|jdd jddgS )Nr1   r   r   r?   -)rP   r8   rw   r   )r"   r@   r)   r$   r$   r%   rh     s
    
zAutoSchema.get_tagsc             C   s   t jdtdd | j||S )NzwMethod `_get_path_parameters()` has been renamed to `get_path_parameters()`. The old name will be removed in DRF v3.14.   )
stacklevel)r+   r,   r   rc   )r"   r@   r)   r$   r$   r%   _get_path_parameters  s    
zAutoSchema._get_path_parametersc             C   s   t jdtdd | j||S )Nz{Method `_get_filter_parameters()` has been renamed to `get_filter_parameters()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   re   )r"   r@   r)   r$   r$   r%   _get_filter_parameters  s    
z!AutoSchema._get_filter_parametersc             C   s   t jdtdd | j||S )NzkMethod `_get_responses()` has been renamed to `get_responses()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   rg   )r"   r@   r)   r$   r$   r%   _get_responses  s    
zAutoSchema._get_responsesc             C   s   t jdtdd | j||S )NzqMethod `_get_request_body()` has been renamed to `get_request_body()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   rf   )r"   r@   r)   r$   r$   r%   _get_request_body  s    
zAutoSchema._get_request_bodyc             C   s   t jdtdd | j||S )NzmMethod `_get_serializer()` has been renamed to `get_serializer()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   rr   )r"   r@   r)   r$   r$   r%   _get_serializer  s    
zAutoSchema._get_serializerc             C   s   t jdtdd | j S )NzkMethod `_get_paginator()` has been renamed to `get_paginator()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   r   )r"   r$   r$   r%   _get_paginator  s    
zAutoSchema._get_paginatorc             C   s   t jdtdd | j||S )NzyMethod `_map_field_validators()` has been renamed to `map_field_validators()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   r   )r"   r   r3   r$   r$   r%   _map_field_validators  s    
z AutoSchema._map_field_validatorsc             C   s   t jdtdd | j|S )NzmMethod `_map_serializer()` has been renamed to `map_serializer()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   rt   )r"   rj   r$   r$   r%   _map_serializer  s    
zAutoSchema._map_serializerc             C   s   t jdtdd | j|S )NzcMethod `_map_field()` has been renamed to `map_field()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   r   )r"   r   r$   r$   r%   
_map_field  s    
zAutoSchema._map_fieldc             C   s   t jdtdd | j|S )NzoMethod `_map_choicefield()` has been renamed to `map_choicefield()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   r   )r"   r   r$   r$   r%   _map_choicefield  s    
zAutoSchema._map_choicefieldc             C   s   t jdtdd | j||S )NzMethod `_get_pagination_parameters()` has been renamed to `get_pagination_parameters()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   rd   )r"   r@   r)   r$   r$   r%   _get_pagination_parameters  s    
z%AutoSchema._get_pagination_parametersc             C   s   t jdtdd | j||S )NzmMethod `_allows_filters()` has been renamed to `allows_filters()`. The old name will be removed in DRF v3.14.r   )r   )r+   r,   r   r   )r"   r@   r)   r$   r$   r%   _allows_filters  s    
zAutoSchema._allows_filters)NNN)+rE   rF   rG   rT   r   r   r   r4   rq   r5   ry   r   ra   rc   re   r   rd   r   r   r   rt   r   r   r   r   rr   r   rf   rg   rh   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r$   r$   )rV   r%   rH   w   sX   %$ $(	)rH   ),rk   r+   collectionsr   r   r   operatorr   urllib.parser   Zdjango.core.validatorsr   r   r   r	   r
   r   r   r   Z	django.dbr   Zdjango.utils.encodingr   Zrest_frameworkr   r   r   r   Zrest_framework.compatr   Zrest_framework.fieldsr   r   Zrest_framework.settingsr   
generatorsr   Z
inspectorsr   utilsr   r   r   rH   r$   r$   r$   r%   <module>   s"   (\