a
    Cgi                     @   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	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 d d	lmZ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)Decimal)
attrgetter)urljoin)DecimalValidatorEmailValidatorMaxLengthValidatorMaxValueValidatorMinLengthValidatorMinValueValidatorRegexValidatorURLValidator)models)	force_str)
exceptions	renderersserializers)
inflection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 ur*| j|d< |S )N )titleversiondescription)r   r   r    )selfinfo r#   ]/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/rest_framework/schemas/openapi.pyget_info   s    

zSchemaGenerator.get_infoc                 C   s   i }|D ]t}|| D ]f}d|| | vr*q|| | d }||v rlt dj|| d || d |||d ||d||< qq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   |    i }i }| |rdn|\}}|D ]\}}}	| |||	sDq*|	j||}
|	j||}| D ]0}||vrvqh|| || krqhtd	| qh|
| |dr|dd }t| jpd|}||i  |
|| | < q*| | d|  |d}t|dkrd|i|d	< |S )
z,
        Generate a OpenAPI schema.
        NzASchema component "{}" has been overridden 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lowerr/   r%   len)r!   requestpublicZcomponents_schemasr-   _Zview_endpointspathr(   view	operationr1   kr2   r#   r#   r$   
get_schema@   s<    


zSchemaGenerator.get_schema)NF)__name__
__module____qualname__r%   r/   rC   r#   r#   r#   r$   r      s   r   c                       s  e Zd Zd> 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   Z!S )?
AutoSchemaNc                    s>   |rt dd |D std|| _|| _|| _t   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>{       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!   tagsrS   rT   	__class__r#   r$   rV   v   s    zAutoSchema.__init__retrievecreater6   ZpartialUpdatedestroy)getpostputpatchdeletec                 C   s   i }|  |||d< | |||d< g }|| ||7 }|| ||7 }|| ||7 }||d< | ||}|rx||d< | |||d< | |||d< |S )Nr&   r    
parametersZrequestBody	responsesrW   )get_operation_idget_descriptionget_path_parametersget_pagination_parametersget_filter_parametersget_request_bodyget_responsesget_tags)r!   r?   r(   rA   rb   request_bodyr#   r#   r$   r3      s    zAutoSchema.get_operationc                 C   sP   | j dur| j S |jj}tdtj}|d|}|dkrLtd|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")	rT   rY   rD   recompile
IGNORECASEsub	Exceptionr,   )r!   rm   rT   patternr#   r#   r$   get_component_name   s    
zAutoSchema.get_component_namec                 C   s   |  dkri S | ||}| ||}i }t|tjrX| |}| |}||| t|tjr| |}| |}||| |S )zN
        Return components with their properties from the serializer.
        ra   )	r:   get_request_serializerget_response_serializerrJ   r   
Serializerrt   map_serializerr9   )r!   r?   r(   Zrequest_serializerZresponse_serializerr1   rT   contentr#   r#   r$   r4      s    



zAutoSchema.get_componentsc                 C   s.   | d}|d ddd |dd  D  S )Nr>   r   r   c                 s   s   | ]}|  V  qd S rH   )r   )rL   xr#   r#   r$   rN      rO   z,AutoSchema._to_camel_case.<locals>.<genexpr>r   )splitjoin)r!   Z	snake_strr1   r#   r#   r$   _to_camel_case   s    
zAutoSchema._to_camel_casec                 C   s   t t | jdddd}| jdur(| j}n|dur8|j}n| ||durp| ||jj}|dr|dd }nX| jjj}|dr|dd }n|dr|dd	 }|| r|dt|  }|d
krt	sJ dt	
|}|S )za
        Compute the base part for operation ID from the model, serializer or view name.
        querysetNmodelrw   iZAPIViewiZViewlistz:`inflection` must be installed for OpenAPI schema support.)getattrr@   rS   rD   get_serializerrY   endswithr   r;   r   Z	pluralize)r!   r?   r(   actionr   namer#   r#   r$   get_operation_id_base   s(    





z AutoSchema.get_operation_id_basec                 C   s`   t | jd| }t||| jr&d}n$|| jvr<| |}n| j|  }| |||}|| S )z^
        Compute an operation ID from the view type and get_operation_id_base method.
        r   r   )r   r@   r:   r   method_mappingr}   r   )r!   r?   r(   method_namer   r   r#   r#   r$   rd      s    
zAutoSchema.get_operation_idc           	   	   C   s   t sJ dtt| jdddd}g }t |D ]}d}|durz|j|}W n tyf   d}Y n0 |dur|jrt|j}n|dur|j	rt
||}|dd|dd	id
}|| q0|S )zL
        Return a list of parameters from templated path variables.
        z;`uritemplate` must be installed for OpenAPI schema support.r~   Nr   r   r?   Ttypestring)r   inrequiredr    r2   )r   r   r@   	variables_meta	get_fieldrr   	help_textr   Zprimary_keyr   append)	r!   r?   r(   r   rb   variabler    model_fieldZ	parameterr#   r#   r$   rf     s.    

	zAutoSchema.get_path_parametersc                 C   s8   |  ||sg S g }| jjD ]}|| | j7 }q|S rH   )allows_filtersr@   filter_backendsget_schema_operation_parameters)r!   r?   r(   rb   Zfilter_backendr#   r#   r$   rh   1  s    z AutoSchema.get_filter_parametersc                 C   s:   t | jdddu rdS t| jdr.| jjdv S | dv 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   rZ   r6   Zpartial_updater\   )r]   r_   r`   ra   )r   r@   hasattrr   r:   r!   r?   r(   r#   r#   r$   r   9  s
    zAutoSchema.allows_filtersc                 C   s0   | j }t|||sg S |  }|s&g S ||S rH   )r@   r   get_paginatorr   )r!   r?   r(   r@   	paginatorr#   r#   r$   rg   F  s    z$AutoSchema.get_pagination_parametersc                 C   s   t t|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 rH   )rJ   boolrL   choicer#   r#   r$   rN   T  rO   z-AutoSchema.map_choicefield.<locals>.<genexpr>booleanc                 s   s   | ]}t |tV  qd S rH   )rJ   intr   r#   r#   r$   rN   V  rO   integerc                 s   s   | ]}t |tttfV  qd S rH   )rJ   r   floatr   r   r#   r#   r$   rN   X  rO   numberc                 s   s   | ]}t |tV  qd S rH   rI   r   r#   r#   r$   rN   [  rO   r   enumr   )r   dictfromkeyschoicesrP   )r!   fieldr   r   mappingr#   r#   r$   map_choicefieldR  s    
zAutoSchema.map_choicefieldc                 C   s$  t |tjrd| |jdS t |tjr@| |}d|d< |S t |tjr^d| |jdS t |tj	rt
|ddr| j|jdS t
|jdd }|d ur|jj}t |tjrdd	iS t |tjrd| |dS t |tjr| |S t |tjr"di d}t |jts| |j|d
< |S t |tjr:dddS t |tjrRdddS t |tjrjdddS t |tjrd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r^t
|dtjrddd}nddi}|j r"t!d|j d d  d |d< |j"rNt#|j"d d |d< |d  |d< | $|| |S t |tj%rddi}| $|| |S t |tj&rdd	i}| $|| t#|'ddd kst#|'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-diS )$Narrayr   itemsobjectr   pk_fieldF)r   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int64binaryr   ).rJ   r   ZListSerializerrx   childrw   ZManyRelatedField	map_fieldZchild_relationZPrimaryKeyRelatedFieldr   r   r~   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IntegerFieldr]   Z	FileFieldZBooleanFieldZ	JSONFieldZ	DictFieldZHStoreFieldrY   )r!   r   datar   r   r   ry   ZFIELD_CLASS_SCHEMA_TYPEr#   r#   r$   r   n  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   ry   r#   r#   r$   r     s    
zAutoSchema._map_min_maxc                 C   s   g }i }|j  D ]}t|tjr$q|jr@|js@|| | | 	|}|j
rXd|d< |jrfd|d< |jrtd|d< |jd ur|jtkrt|js|j|d< |jrt|j|d< | || ||| |< qd|d}|r||d	< |S )
NTZreadOnlyZ	writeOnlyZnullabledefaultr    r   )r   
propertiesr   )fieldsvaluesrJ   r   ZHiddenFieldr   partialr   get_field_namer   Z	read_onlyZ
write_onlyZ
allow_nullr   r   callabler   rK   map_field_validators)r!   rm   r   r   r   r2   resultr#   r#   r$   rx     s4    

zAutoSchema.map_serializerc                 C   sd  |j D ]V}t|trd|d< t|tr0d|d< t|trP|jjdd|d< qt|trzd}t|t	j
rnd}|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rt|dtjs|jrtd|jd d  d |d< |jr|j}|jdur<|jdkr<||j8 }t|d d |d< |d  |d< qdS )z&
        map field validators
        r   r,   r   z\Zz\zrs   Z	maxLengthZmaxItemsZ	minLengthZminItemsr   r   r   r   r   r   r   r   Nr   r   )Z
validatorsrJ   r   r   r   regexrs   replacer   r   r   Zlimit_valuer	   r   r
   r   r   r   r   r   r   Z
max_digitsr   )r!   r   r2   v	attr_namedigitsr#   r#   r$   r   (  s@    








zAutoSchema.map_field_validatorsc                 C   s   |j S )z
        Override this method if you want to change schema field name.
        For example, convert snake_case field name to camelCase.
        )
field_name)r!   r   r#   r#   r$   r   P  s    zAutoSchema.get_field_namec                 C   s   t | jdd }|r| S d S )Npagination_class)r   r@   )r!   r   r#   r#   r$   r   W  s    zAutoSchema.get_paginatorc                 C   s   t ttd| jjS )N
media_type)r   mapr   r@   Zparser_classesr   r#   r#   r$   map_parsers]  s    zAutoSchema.map_parsersc                 C   s0   g }| j jD ]}t|tjrq||j q|S rH   )r@   Zrenderer_classes
issubclassr   ZBrowsableAPIRendererr   r   )r!   r?   r(   Zmedia_typesZrendererr#   r#   r$   map_renderers`  s    zAutoSchema.map_renderersc              
   C   sR   | j }t|dsd S z
| W S  tjyL   td|jj	|| Y d S 0 d S )Nr   zt{}.get_serializer() raised an exception during schema generation. Serializer fields will not be generated for {} {}.)
r@   r   r   r   ZAPIExceptionr*   r+   r,   rY   rD   )r!   r?   r(   r@   r#   r#   r$   r   i  s    


zAutoSchema.get_serializerc                 C   s   |  ||S )zr
        Override this method if your view uses a different serializer for
        handling request body.
        r   r   r#   r#   r$   ru   x  s    z!AutoSchema.get_request_serializerc                 C   s   |  ||S )zu
        Override this method if your view uses a different serializer for
        populating response data.
        r   r   r#   r#   r$   rv     s    z"AutoSchema.get_response_serializerc                 C   s   dd | |iS )Nz$refz#/components/schemas/{})r,   rt   )r!   rm   r#   r#   r$   get_reference  s    zAutoSchema.get_referencec                    sZ   |dvri S |  ||| _| ||}t|tjs8i  n
| | d fdd| jD iS )N)PUTPATCHPOSTry   c                    s   i | ]}|d  iqS r2   r#   rL   ctitem_schemar#   r$   
<dictcomp>  s   z/AutoSchema.get_request_body.<locals>.<dictcomp>)r   request_media_typesru   rJ   r   rw   r   )r!   r?   r(   rm   r#   r   r$   ri     s    
zAutoSchema.get_request_bodyc                    s   |dkrdddiiS |  ||| _| ||}t|tjs@i }n
| |}t||| jrzd|d | 	 }|r~|
  n| |dkrdnd	}| fd
d| jD ddiS )NDELETEZ204r    r   r   r   r   Z201Z200c                    s   i | ]}|d  iqS r   r#   r   Zresponse_schemar#   r$   r     s   z,AutoSchema.get_responses.<locals>.<dictcomp>)ry   r    )r   response_media_typesrv   rJ   r   rw   r   r   r@   r   Zget_paginated_response_schema)r!   r?   r(   rm   r   r   status_coder#   r   r$   rj     s4    

zAutoSchema.get_responsesc                 C   s:   | j r| j S |dr"|dd  }|dd ddgS )Nr0   r   r   r>   -)rR   r7   r{   r   r   r#   r#   r$   rk     s
    
zAutoSchema.get_tags)NNN)"rD   rE   rF   rV   r   r   r   r3   rt   r4   r}   r   rd   rf   rh   r   rg   r   r   r   rx   r   r   r   r   r   r   ru   rv   r   ri   rj   rk   __classcell__r#   r#   rX   r$   rG   t   sH   &$ $(	)rG   )*rn   r*   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   Zrest_framework.compatr   r   Zrest_framework.fieldsr   r   Zrest_framework.settingsr   
generatorsr   Z
inspectorsr   utilsr   r   r   rG   r#   r#   r#   r$   <module>   s    (\