o
    ÖèFhbj  ã                   @   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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)ÚRemovedInDRF315WarningÚ
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$   úW/var/www/html/loop/nvenv/lib/python3.10/site-packages/rest_framework/schemas/openapi.pyÚget_info   s   þ

zSchemaGenerator.get_infoc                 C   s‚   i }|D ]:}|| D ]3}d|| | vrq
|| | d }||v r6t  dj|| d || d |||d�¡ ||dœ||< q
qd S )NÚoperationIdzîYou 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)Úroute1Úmethod1Úroute2Ú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 ]^\}}}	|  |||	¡s"q|	j ||¡}
|	j ||¡}| ¡ D ]}||vr;q4|| || krDq4t d 	|¡¡ q4| 
|¡ | d¡r]|dd… }t| jpbd|ƒ}| |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)Úopenapir#   r2   r   ÚschemasÚ
components)Ú_initialise_endpointsÚ_get_paths_and_endpointsÚhas_view_permissionsÚschemaÚget_operationÚget_componentsÚkeysr/   r0   r1   ÚupdateÚ
startswithr   ÚurlÚ
setdefaultÚlowerr4   r&   Úlen)r"   ÚrequestÚpublicÚcomponents_schemasr2   Ú_Úview_endpointsÚpathr)   ÚviewÚ	operationr8   Úkr<   r$   r$   r%   Ú
get_schemaB   s<   


ýÿzSchemaGenerator.get_schema)NF)Ú__name__Ú
__module__Ú__qualname__r&   r4   rO   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 d>d?„ Z!‡  Z"S )AÚ
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   ó   � | ]}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"   Útagsr`   ra   ©Ú	__class__r$   r%   rc   x   s   zAutoSchema.__init__ÚretrieveÚcreater@   ÚpartialUpdateÚdestroy)ÚgetÚpostÚputÚpatchÚdeletec                 C   sœ   i }|   ||¡|d< |  ||¡|d< g }||  ||¡7 }||  ||¡7 }||  ||¡7 }||d< |  ||¡}|r<||d< |  ||¡|d< |  ||¡|d< |S )Nr'   r!   Ú
parametersÚrequestBodyÚ	responsesrd   )Úget_operation_idÚget_descriptionÚget_path_parametersÚget_pagination_parametersÚget_filter_parametersÚget_request_bodyÚget_responsesÚget_tags)r"   rK   r)   rM   rp   Úrequest_bodyr$   r$   r%   r=   �   s   zAutoSchema.get_operationc                 C   sP   | j dur| j S |jj}t dtj¡}| d|¡}|dkr&t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")	ra   rf   rP   ÚreÚcompileÚ
IGNORECASEÚsubÚ	Exceptionr1   )r"   r|   ra   Úpatternr$   r$   r%   Úget_component_name£   s   

ýzAutoSchema.get_component_namec                 C   sˆ   |  ¡ dkri S |  ||¡}|  ||¡}i }t|tjƒr,|  |¡}|  |¡}| ||¡ t|tjƒrB|  |¡}|  |¡}| ||¡ |S )zN
        Return components with their properties from the serializer.
        ro   )	rD   Úget_request_serializerÚget_response_serializerrW   r   Ú
Serializerrƒ   Úmap_serializerrC   )r"   rK   r)   Úrequest_serializerÚresponse_serializerr8   ra   Úcontentr$   r$   r%   r>   º   s   



zAutoSchema.get_componentsc                 C   s.   |  d¡}|d d dd„ |dd … D ƒ¡ S )NrI   r   r   c                 s   s   � | ]}|  ¡ V  qd S rU   )r   )rY   Úxr$   r$   r%   r[   ×   s   € z,AutoSchema._to_camel_case.<locals>.<genexpr>r   )ÚsplitÚjoin)r"   Ú	snake_strr8   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}nP|dur|j}nH|  ||¡dur8|  ||¡jj}| d¡r7|dd… }n,| jjj}| d¡rI|dd… }n| d¡rT|dd	… }| | ¡ ¡rd|dt|ƒ … }|d
krst	snJ dƒ‚t	 
|¡}|S )za
        Compute the base part for operation ID from the model, serializer or view name.
        ÚquerysetNÚmodelr†   iöÿÿÿÚAPIViewiùÿÿÿÚViewéüÿÿÿÚlistz:`inflection` must be installed for OpenAPI schema support.)ÚgetattrrL   r`   rP   Úget_serializerrf   Úendswithr   rE   r   Ú	pluralize)r"   rK   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–   rL   rD   r   Úmethod_mappingr�   rœ   )r"   rK   r)   Úmethod_namerš   r›   r$   r$   r%   rs   ÿ   s   
zAutoSchema.get_operation_idc           	   	   C   s¾   t sJ dƒ‚tt| jddƒddƒ}g }t  |¡D ]D}d}|durMz|j |¡}W n ty3   d}Y nw |durA|jrAt|jƒ}n|durM|j	rMt
||ƒ}|dd|dd	id
œ}| |¡ q|S )zL
        Return a list of parameters from templated path variables.
        z;`uritemplate` must be installed for OpenAPI schema support.r�   Nr‘   r   rK   TÚtypeÚstring)r›   ÚinÚrequiredr!   r<   )r   r–   rL   Ú	variablesÚ_metaÚ	get_fieldr�   Ú	help_textr   Úprimary_keyr   Úappend)	r"   rK   r)   r‘   rp   Úvariabler!   Úmodel_fieldÚ	parameterr$   r$   r%   ru     s0   ÿ
ÿû	zAutoSchema.get_path_parametersc                 C   s8   |   ||¡sg S g }| jjD ]}||ƒ  | j¡7 }q|S rU   )Úallows_filtersrL   Úfilter_backendsÚget_schema_operation_parameters)r"   rK   r)   rp   Úfilter_backendr$   r$   r%   rw   3  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•   rg   r@   Úpartial_updaterj   )rk   rm   rn   ro   )r–   rL   Úhasattrrš   rD   ©r"   rK   r)   r$   r$   r%   r¬   ;  s
   zAutoSchema.allows_filtersc                 C   s0   | j }t|||ƒsg S |  ¡ }|sg S | |¡S rU   )rL   r   Úget_paginatorr®   )r"   rK   r)   rL   Ú	paginatorr$   r$   r%   rv   H  s   
z$AutoSchema.get_pagination_parametersc                 C   sŒ   t t |j¡ƒ}tdd„ |D ƒƒrd}n&tdd„ |D ƒƒr d}ntdd„ |D ƒƒr,d}ntdd„ |D ƒƒr8d	}nd }d
|i}|rD||d< |S )Nc                 s   rT   rU   )rW   Úbool©rY   Úchoicer$   r$   r%   r[   V  r\   z-AutoSchema.map_choicefield.<locals>.<genexpr>Úbooleanc                 s   rT   rU   )rW   Úintr¶   r$   r$   r%   r[   X  r\   Úintegerc                 s   s    � | ]}t |tttfƒV  qd S rU   )rW   r¹   Úfloatr   r¶   r$   r$   r%   r[   Z  s   € Únumberc                 s   rT   rU   rV   r¶   r$   r$   r%   r[   ]  r\   r    ÚenumrŸ   )r•   ÚdictÚfromkeysÚchoicesr]   )r"   ÚfieldrÀ   rŸ   Úmappingr$   r$   r%   Úmap_choicefieldT  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	ƒr[t
|ddƒrB| j|jd�S t
|jdd ƒ}|d ur[|jj}t |tjƒr[dd	iS t |tjƒrid|  |¡dœS t |tjƒrt|  |¡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ƒr¥dddœS t |tjƒr°dddœS t |tjƒr»dddœS t |tjƒrÆdddœS t |tjƒrÜddi}|jdkrÚ|j|d< |S t |tjƒ�r%t
|dtjƒrðdddœ}nddi}|j �rt!d|j d d  d ƒ|d< |j"�rt#|j"d ƒd |d< |d  |d< |  $||¡ |S t |tj%ƒ�r8ddi}|  $||¡ |S t |tj&ƒ�redd	i}|  $||¡ t#| 'dd¡ƒd k�s_t#| 'dd¡ƒd k�rcd!|d< |S t |tj(ƒ�rqd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Ÿ   r1   z	date-timeÚemailÚuriÚuuidÚbothr1   Úcoerce_to_stringÚdecimalr¼   Ú.r   Ú0Ú1Ú
multipleOfÚ9ÚmaximumÚminimumr   iÿÿÿÚint64Úbinaryr¸   ).rW   r   ÚListSerializerr‡   Úchildr†   ÚManyRelatedFieldÚ	map_fieldÚchild_relationÚPrimaryKeyRelatedFieldr–   rÈ   r�   r¤   Úpkr   Ú	AutoFieldÚMultipleChoiceFieldrÃ   ÚChoiceFieldÚ	ListFieldr   Ú	DateFieldÚDateTimeFieldÚ
EmailFieldÚURLFieldÚ	UUIDFieldÚIPAddressFieldÚprotocolÚDecimalFieldr   ÚCOERCE_DECIMAL_TO_STRINGÚdecimal_placesr»   Úmax_whole_digitsr¹   Ú_map_min_maxÚ
FloatFieldÚIntegerFieldrk   Ú	FileFieldÚBooleanFieldÚ	JSONFieldÚ	DictFieldÚHStoreFieldrf   )r"   rÁ   Údatar‘   rª   rÂ   rŠ   ÚFIELD_CLASS_SCHEMA_TYPEr$   r$   r%   rÜ   p  s¾   
þ

þþ
þþþþþþÿ

þÿÿÿ,þüzAutoSchema.map_fieldc                 C   s(   |j r|j |d< |jr|j|d< d S d S )NrÕ   rÖ   )Ú	max_valueÚ	min_value)r"   rÁ   rŠ   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
r,d|d< |jr3d|d< |jr:d|d< |jd urN|jtkrNt|jƒsN|j|d< |jrXt|jƒ|d< |  ||¡ |||  |¡< q	d|dœ}|rq||d	< |S )
NTÚreadOnlyÚ	writeOnlyÚnullableÚdefaultr!   rÇ   )rŸ   Ú
propertiesr¢   )ÚfieldsÚvaluesrW   r   ÚHiddenFieldr¢   Úpartialr¨   Úget_field_namerÜ   Ú	read_onlyÚ
write_onlyÚ
allow_nullrþ   r   Úcallabler¦   rX   Úmap_field_validators)r"   r|   r¢   rÿ   rÁ   r<   Úresultr$   r$   r%   r‡     s4   

þzAutoSchema.map_serializerc                 C   s\  |j D ]¨}t|tƒrd|d< t|tƒrd|d< t|tƒr'|jj dd¡|d< qt|tƒr<d}t|t	j
ƒr6d}|j||< qt|tƒrQd	}t|t	j
ƒrKd
}|j||< qt|tƒr\|j|d< qt|tƒrg|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Ê   r1   rË   z\Zz\zr‚   Ú	maxLengthÚmaxItemsÚ	minLengthÚminItemsrÕ   rÖ   rÎ   rÐ   r   rÑ   rÒ   rÓ   Nr   rÔ   )Ú
validatorsrW   r   r   r   Úregexr‚   Úreplacer   r   rã   Úlimit_valuer	   r   r
   r   r–   r   rì   rí   r»   Ú
max_digitsr¹   )r"   rÁ   r<   ÚvÚ	attr_nameÚdigitsr$   r$   r%   r	  *  sD   








ÿ
€Þ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  R  s   zAutoSchema.get_field_namec                 C   s   t | jdd ƒ}|r|ƒ S d S )NÚpagination_class)r–   rL   )r"   r  r$   r$   r%   r³   Y  s   zAutoSchema.get_paginatorc                 C   s   t ttdƒ| jjƒƒS )NÚ
media_type)r•   Úmapr   rL   Ú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 rU   )rL   Úrenderer_classesÚ
issubclassr   ÚBrowsableAPIRendererr¨   r  )r"   rK   r)   Úmedia_typesÚrendererr$   r$   r%   Úmap_renderersb  s   zAutoSchema.map_renderersc              
   C   sN   | j }t|dƒs
d S z| ¡ W S  tjy&   t d |jj	||¡¡ Y d S w )Nr—   zt{}.get_serializer() raised an exception during schema generation. Serializer fields will not be generated for {} {}.)
rL   r±   r—   r   ÚAPIExceptionr/   r0   r1   rf   rP   )r"   rK   r)   rL   r$   r$   r%   r—   k  s   

ýûzAutoSchema.get_serializerc                 C   ó   |   ||¡S )zr
        Override this method if your view uses a different serializer for
        handling request body.
        ©r—   r²   r$   r$   r%   r„   z  ó   z!AutoSchema.get_request_serializerc                 C   r$  )zu
        Override this method if your view uses a different serializer for
        populating response data.
        r%  r²   r$   r$   r%   r…   �  r&  z"AutoSchema.get_response_serializerc                 C   s   dd  |  |¡¡iS )Nz$refz#/components/schemas/{})r1   rƒ   ©r"   r|   r$   r$   r%   Úget_referenceˆ  s   zAutoSchema.get_referencec                    sZ   |dvri S |   ||¡| _|  ||¡}t|tjƒsi ‰ n|  |¡‰ d‡ fdd„| jD ƒiS )N)ÚPUTÚPATCHÚPOSTrŠ   c                    ó   i | ]}|d ˆ i“qS ©r<   r$   ©rY   Úct©Úitem_schemar$   r%   Ú
<dictcomp>™  ó    ÿÿz/AutoSchema.get_request_body.<locals>.<dictcomp>)r  Úrequest_media_typesr„   rW   r   r†   r(  )r"   rK   r)   r|   r$   r0  r%   rx   ‹  s   
þÿzAutoSchema.get_request_bodyc                    s¬   |dkr
dddiiS |   ||¡| _|  ||¡}t|tjƒs i }n|  |¡}t||| jƒr=d|dœ‰ |  	¡ }|r<| 
ˆ ¡‰ n|‰ |dkrEdnd	}|‡ fd
d„| jD ƒddœiS )NÚDELETEÚ204r!   r   rÄ   rÅ   r+  Ú201Ú200c                    r,  r-  r$   r.  ©Úresponse_schemar$   r%   r2  ½  r3  z,AutoSchema.get_responses.<locals>.<dictcomp>)rŠ   r!   )r"  Úresponse_media_typesr…   rW   r   r†   r(  r   rL   r³   Úget_paginated_response_schema)r"   rK   r)   r|   r1  r´   Ústatus_coder$   r9  r%   ry   Ÿ  s6   ÿÿ
þ
€
þøÿzAutoSchema.get_responsesc                 C   s:   | j r| j S | d¡r|dd … }| d¡d  dd¡gS )Nr5   r   r   rI   ú-)r_   rA   rŒ   r  r²   r$   r$   r%   rz   È  s
   
zAutoSchema.get_tagsc                 C   s   t jdtdd� |  |¡S )NzkMethod `_get_reference()` has been renamed to `get_reference()`. The old name will be removed in DRF v3.15.é   )Ú
stacklevel)r/   r0   r   r(  r'  r$   r$   r%   Ú_get_referenceÕ  s
   ý
zAutoSchema._get_reference)NNN)#rP   rQ   rR   rc   r4  r;  r�   r=   rƒ   r>   r�   rœ   rs   ru   rw   r¬   rv   rÃ   rÜ   rï   r‡   r	  r  r³   r  r"  r—   r„   r…   r(  rx   ry   rz   rA  Ú__classcell__r$   r$   re   r%   rS   v   sL    û&$ $(	)rS   )+r}   r/   rÏ   r   Úoperatorr   Úurllib.parser   Údjango.core.validatorsr   r   r   r   r	   r
   r   r   Ú	django.dbr   Údjango.utils.encodingr   Úrest_frameworkr   r   r   r   Úrest_framework.compatr   r   Úrest_framework.fieldsr   r   Úrest_framework.settingsr   Ú
generatorsr   Ú
inspectorsr   Úutilsr   r   r   rS   r$   r$   r$   r%   Ú<module>   s"    (\