a
    còf£S  ã                   @   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
mZmZ d dlmZ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 dd„ Zdd„ Zdd„ ZdZG dd„ deƒZdd„ Z G dd„ deƒZ!dd„ Z"G dd„ deƒZ#G dd„ deƒZ$d d!„ Z%dS )"é    N)ÚCounter)Úparse)Úmodels)Ú	force_str)ÚRemovedInDRF317WarningÚ
exceptionsÚserializers)ÚcoreapiÚ
coreschemaÚuritemplate)Úapi_settingsé   )ÚBaseSchemaGenerator)ÚViewInspector)Úget_pk_descriptionÚis_list_viewc                 C   s^   dd„ | D ƒ}t |ƒ}t|ƒ}|}t|ƒD ]$\}}||| kr*|d |… } qPq*dd |¡ S )Nc                 S   s   g | ]}|  d ¡ d ¡‘qS )ú/)ÚstripÚsplit)Ú.0Úpath© r   ú[/home/httpd/docs/test/DocsMgr/lib/python3.9/site-packages/rest_framework/schemas/coreapi.pyÚ
<listcomp>   ó    zcommon_path.<locals>.<listcomp>r   )ÚminÚmaxÚ	enumerateÚjoin)ÚpathsÚsplit_pathsÚs1Ús2ÚcommonÚiÚcr   r   r   Úcommon_path   s    r&   c                 C   s   | dvS )N>   ÚretrieveÚdestroyÚcreateÚpartial_updateÚupdateÚlistr   )Úactionr   r   r   Úis_custom_action   s    r.   c                 C   s@   |   ¡ D ]\}}t|ƒ q| jD ]\}}|  |¡}|| |< q d S ©N)ÚitemsÚdistribute_linksÚlinksÚget_available_key)ÚobjÚkeyÚvalueÚpreferred_keyÚlinkr   r   r   r1   #   s
    

r1   a=  
Schema Naming Collision.

coreapi.Link for URL path {value_url} cannot be inserted into schema.
Position conflicts with coreapi.Link for URL path {target_url}.

Attempted to insert link with keys: {keys}.

Adjust URLs to avoid naming collision or override `SchemaGenerator.get_keys()`
to customise schema structure.
c                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )ÚLinkNodec                    s   g | _ tƒ | _tƒ  ¡  d S r/   )r2   r   Úmethods_counterÚsuperÚ__init__)Úself©Ú	__class__r   r   r<   :   s    zLinkNode.__init__c                 C   sF   || vr|S | j | }| j |  d7  < d ||¡}|| vr|S qd S )Nr   z{}_{})r:   Úformat)r=   r7   Zcurrent_valr5   r   r   r   r3   ?   s    
zLinkNode.get_available_key)Ú__name__Ú
__module__Ú__qualname__r<   r3   Ú__classcell__r   r   r>   r   r9   9   s   r9   c                 C   sx   |dd… D ]}|| vr"t ƒ | |< | | } qz| j |d |f¡ W n. tyr   tj|j| j|d�}t|ƒ‚Y n0 dS )zÌ
    Nested dictionary insertion.

    >>> example = {}
    >>> insert_into(example, ['a', 'b', 'c'], 123)
    >>> example
    LinkNode({'a': LinkNode({'b': LinkNode({'c': LinkNode(links=[123])}}})))
    Néÿÿÿÿ)Z	value_urlÚ
target_urlÚkeys)r9   r2   ÚappendÚ	TypeErrorÚINSERT_INTO_COLLISION_FMTr@   ÚurlÚ
ValueError)ÚtargetrG   r6   r5   Úmsgr   r   r   Úinsert_intoL   s    	

ýrO   c                       sZ   e Zd ZdZddddddœZdZd‡ fd	d
„	Zddd„Zddd„Zdd„ Z	dd„ Z
‡  ZS )ÚSchemaGeneratorz#
    Original CoreAPI version.
    r'   r)   r+   r*   r(   )ÚgetÚpostÚputÚpatchÚdeleteNc                    sL   t sJ dƒ‚t d ur t dt¡ ts,J dƒ‚tƒ  |||||¡ tj| _	d S )Nz/`coreapi` must be installed for schema support.úCCoreAPI compatibility is deprecated and will be removed in DRF 3.17z2`coreschema` must be installed for schema support.)
r	   ÚwarningsÚwarnr   r
   r;   r<   r   ZSCHEMA_COERCE_METHOD_NAMESÚcoerce_method_names)r=   ÚtitlerK   ÚdescriptionÚpatternsZurlconfÚversionr>   r   r   r<   w   s    zSchemaGenerator.__init__c                 C   sˆ   t ƒ }|  |¡\}}|sdS |  |¡}|D ]X\}}}|  |||¡sDq*|jj||| jd�}	|t|ƒd… }
|  |
||¡}t	|||	ƒ q*|S )zq
        Return a dictionary containing all the links that should be
        included in the API schema.
        N)Úbase_url)
r9   Z_get_paths_and_endpointsÚdetermine_path_prefixZhas_view_permissionsÚschemaÚget_linkrK   ÚlenÚget_keysrO   )r=   Úrequestr2   r   Zview_endpointsÚprefixr   ÚmethodÚviewr8   ÚsubpathrG   r   r   r   Ú	get_links€   s    
zSchemaGenerator.get_linksFc                 C   sZ   |   ¡  |  |rdn|¡}|s"dS | j}|s<|dur<| ¡ }t|ƒ tj| j| j||d�S )zL
        Generate a `coreapi.Document` representing the API schema.
        N)rZ   r[   rK   Úcontent)	Z_initialise_endpointsri   rK   Zbuild_absolute_urir1   r	   ZDocumentrZ   r[   )r=   rd   Úpublicr2   rK   r   r   r   Ú
get_schema˜   s    þzSchemaGenerator.get_schemac                 C   sÌ   t |dƒr|j}n t|||ƒr$d}n| j| ¡  }dd„ | d¡ d¡D ƒ}t|ƒr®dd„ |jD ƒ}t	|ƒdkrœ| j| ¡  }|| j
v r’| j
| }||g S |d	d
… |g S || j
v rÂ| j
| }||g S )a�  
        Return a list of keys that should be used to layout a link within
        the schema document.

        /users/                   ("users", "list"), ("users", "create")
        /users/{pk}/              ("users", "read"), ("users", "update"), ("users", "delete")
        /users/enabled/           ("users", "enabled")  # custom viewset list action
        /users/{pk}/star/         ("users", "star")     # custom viewset detail action
        /users/{pk}/groups/       ("users", "groups", "list"), ("users", "groups", "create")
        /users/{pk}/groups/{pk}/  ("users", "groups", "read"), ("users", "groups", "update"), ("users", "groups", "delete")
        r-   r,   c                 S   s   g | ]}d |vr|‘qS )Ú{r   )r   Ú	componentr   r   r   r   Ã   s   þz,SchemaGenerator.get_keys.<locals>.<listcomp>r   c                 S   s   h | ]}|d kr|’qS )Úheadr   )r   rf   r   r   r   Ú	<setcomp>Ë   s   z+SchemaGenerator.get_keys.<locals>.<setcomp>r   NrE   )Úhasattrr-   r   Údefault_mappingÚlowerr   r   r.   Z
action_maprb   rY   )r=   rh   rf   rg   r-   Znamed_path_componentsZmapped_methodsr   r   r   rc   ­   s*    
þþ




zSchemaGenerator.get_keysc                 C   sx   g }|D ]f}|  d¡ d¡}g }|D ]}d|v r4 q@| |¡ q$d |dd… ¡}|s\ dS | d| d ¡ qt|ƒS )a™  
        Given a list of all paths, return the common prefix which should be
        discounted when generating a schema structure.

        This will be the longest common string that does not include that last
        component of the URL, or the last component before a path parameter.

        For example:

        /api/v1/users/
        /api/v1/users/{pk}/

        The path prefix is '/api/v1'
        r   rm   NrE   )r   r   rH   r   r&   )r=   r   Úprefixesr   Ú
componentsZinitial_componentsrn   re   r   r   r   r_   Ý   s    z%SchemaGenerator.determine_path_prefix)NNNNNN)N)NF)rA   rB   rC   Ú__doc__rr   rY   r<   ri   rl   rc   r_   rD   r   r   r>   r   rP   e   s   û	

0rP   c                 C   sb  | j rt| j ƒnd}| jr$t| jƒnd}t| tjtjfƒrTt| jƒ}t	j
|||d�S t| tjƒrnt	j||d�S t| tjƒršt	jdd„ | j ¡ D ƒ||d�S t| tjƒrÀt| jƒ}t	j
|||d�S t| tjƒ�rt	j}t| jdd ƒ}|d u�r|jj}t|tjƒ�rt	j}|||d�S t| tjƒ�r0t	j||d�S t| tjƒ�r\t	j
t	jt| jƒd�||d�S t| tj ƒ�r€t	jt| jƒ||d	�S t| tj!ƒ�rœt	j"||d�S t| tj#tj$fƒ�r¾t	j%||d�S t| tj&ƒ�rÚt	j||d�S t| tj'ƒ�røt	j||d
d�S t| tj(ƒ�rt	j||dd�S t| tj)ƒ�r2t	j||d�S | j* +d¡dk�rTt	j||dd�S t	j||d�S )NÚ )r0   rZ   r[   ©rZ   r[   c                 S   s   i | ]\}}|t |ƒ“qS r   )Úfield_to_schema)r   r5   r6   r   r   r   Ú
<dictcomp>  s   ÿz#field_to_schema.<locals>.<dictcomp>)Ú
propertiesrZ   r[   Úmodel)Úenum)r}   rZ   r[   Údate)rZ   r[   r@   z	date-timeZbase_templateztextarea.htmlÚtextarea),Úlabelr   Ú	help_textÚ
isinstancer   ÚListSerializerZ	ListFieldry   Úchildr
   ÚArrayZ	DictFieldZObjectÚ
SerializerÚfieldsr0   ZManyRelatedFieldZchild_relationZPrimaryKeyRelatedFieldÚStringÚgetattrÚquerysetÚ_metaÚpkr   Ú	AutoFieldÚIntegerZRelatedFieldZMultipleChoiceFieldÚEnumr,   ÚchoicesZChoiceFieldZBooleanFieldÚBooleanZDecimalFieldZ
FloatFieldÚNumberZIntegerFieldZ	DateFieldZDateTimeFieldZ	JSONFieldÚstylerQ   )ÚfieldrZ   r[   Zchild_schemaZrelated_field_schemaÚ
schema_clsr|   Úmodel_fieldr   r   r   ry   ÿ   sœ    
ýþýù	
ý
ýýýýýry   c                       sn   e Zd ZdZd‡ fdd„	Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zedd„ ƒZdd„ Z‡  ZS )Ú
AutoSchemazj
    Default inspector for APIView

    Responsible for per-view introspection and schema generation.
    Nc                    s4   t ƒ  ¡  tdurt dt¡ |du r*g }|| _dS )z°
        Parameters:

        * `manual_fields`: list of `coreapi.Field` instances that
            will be added to auto-generated fields, overwriting on `Field.name`
        NrV   )r;   r<   r	   rW   rX   r   Ú_manual_fields)r=   Úmanual_fieldsr>   r   r   r<   \  s    
zAutoSchema.__init__c                 C   sÂ   |   ||¡}||  ||¡7 }||  ||¡7 }||  ||¡7 }|  ||¡}|  ||¡}|rxtdd„ |D ƒƒrx|  ||¡}nd}|  ||¡}|r¢| 	d¡r¢|dd… }t
jt ||¡| ¡ |||d�S )a7  
        Generate `coreapi.Link` for self.view, path and method.

        This is the main _public_ access point.

        Parameters:

        * path: Route path for view from URLConf.
        * method: The HTTP request method.
        * base_url: The project "mount point" as given to SchemaGenerator
        c                 S   s   g | ]}|j d v ‘qS ))ÚformÚbody)Úlocation)r   r”   r   r   r   r     r   z'AutoSchema.get_link.<locals>.<listcomp>Nr   r   ©rK   r-   Úencodingr‡   r[   )Úget_path_fieldsÚget_serializer_fieldsÚget_pagination_fieldsÚget_filter_fieldsÚget_manual_fieldsÚupdate_fieldsÚanyÚget_encodingÚget_descriptionÚ
startswithr	   ÚLinkr   Úurljoinrs   )r=   r   rf   r^   r‡   r™   rž   r[   r   r   r   ra   k  s&    
ûzAutoSchema.get_linkc              
   C   s  | j }tt|ddƒddƒ}g }t |¡D ]î}d}d}tj}	i }
|durêz|j |¡}W n tyl   d}Y n0 |dur†|j	r†t
|j	ƒ}|dur |jr t
|jƒ}n|dur¸|jr¸t||ƒ}t|dƒrØ|j|krØ|j|
d< nt|tjƒrêtj}	tj|dd|	f ||d	œ|
¤Žd
�}| |¡ q(|S )zs
        Return a list of `coreapi.Field` instances corresponding to any
        templated path variables.
        rŠ   Nr|   rw   Úlookup_value_regexÚpatternr   Trx   ©Únamerœ   Úrequiredr`   )rg   r‰   r   Ú	variablesr
   rˆ   r‹   Ú	get_fieldÚ	ExceptionZverbose_namer   r�   Zprimary_keyr   rq   Zlookup_fieldr«   r‚   r   r�   rŽ   r	   ÚFieldrH   )r=   r   rf   rg   r|   r‡   ÚvariablerZ   r[   r•   Úkwargsr–   r”   r   r   r   rŸ   ‘  s>    


üzAutoSchema.get_path_fieldsc              
   C   sî   | j }|dvrg S t|dƒs g S z| ¡ }W n0 tjy\   d}t d |jj	||¡¡ Y n0 t
|tjƒr‚tjdddt ¡ d�gS t
|tjƒs’g S g }|j ¡ D ]H}|js t
|tjƒr¸q |joÄ|d	k}tj|jd
|t|ƒd�}| |¡ q |S )z”
        Return a list of `coreapi.Field` instances corresponding to any
        request body input, as determined by the serializer class.
        )ÚPUTÚPATCHÚPOSTÚget_serializerNzt{}.get_serializer() raised an exception during schema generation. Serializer fields will not be generated for {} {}.Údatar›   Tr­   r·   rš   )rg   rq   r¹   r   ZAPIExceptionrW   rX   r@   r?   rA   r‚   r   rƒ   r	   r³   r
   r…   r†   r‡   ÚvaluesZ	read_onlyZHiddenFieldr¯   Ú
field_namery   rH   )r=   r   rf   rg   Ú
serializerr‡   r”   r¯   r   r   r   r    ½  sF    

ýüÿ	üz AutoSchema.get_serializer_fieldsc                 C   s<   | j }t|||ƒsg S t|dd ƒ}|s*g S | ¡ }| |¡S )NÚpagination_class)rg   r   r‰   r¾   Úget_schema_fields)r=   r   rf   rg   Z
paginationZ	paginatorr   r   r   r¡   ð  s    z AutoSchema.get_pagination_fieldsc                 C   s:   t | jddƒdu rdS t| jdƒr.| jjdv S | ¡ dv S )až  
        Determine whether to include filter Fields in schema.

        Default implementation looks for ModelViewSet or GenericAPIView
        actions/methods that cause filtering on the default implementation.

        Override to adjust behaviour for your view.

        Note: Introduced in v3.7: Initially "private" (i.e. with leading underscore)
            to allow changes based on user experience.
        Úfilter_backendsNFr-   )r,   r'   r+   r*   r(   )rQ   rS   rT   rU   )r‰   rg   rq   r-   rs   ©r=   r   rf   r   r   r   Ú_allows_filtersý  s
    zAutoSchema._allows_filtersc                 C   s8   |   ||¡sg S g }| jjD ]}||ƒ  | j¡7 }q|S r/   )rÂ   rg   rÀ   r¿   )r=   r   rf   r‡   Zfilter_backendr   r   r   r¢     s    zAutoSchema.get_filter_fieldsc                 C   s   | j S r/   )r˜   rÁ   r   r   r   r£     s    zAutoSchema.get_manual_fieldsc                 C   s:   |s| S dd„ | D ƒ}|D ]}|||j < qt| ¡ ƒ} | S )ay  
        Update list of coreapi.Field instances, overwriting on `Field.name`.

        Utility function to handle replacing coreapi.Field fields
        from a list by name. Used to handle `manual_fields`.

        Parameters:

        * `fields`: list of `coreapi.Field` instances to update
        * `update_with: list of `coreapi.Field` instances to add or replace.
        c                 S   s   i | ]}|j |“qS r   )r®   ©r   Úfr   r   r   rz   -  r   z,AutoSchema.update_fields.<locals>.<dictcomp>)r®   r,   r»   )r‡   Zupdate_withZby_namerÄ   r   r   r   r¤     s    zAutoSchema.update_fieldsc                 C   sR   | j }h d£}t|dg ƒ}|D ].}t|ddƒ}||v r>|  S |dkr dS qdS )zN
        Return the 'encoding' parameter to use for a given endpoint.
        >   zmultipart/form-datazapplication/jsonz!application/x-www-form-urlencodedÚparser_classesÚ
media_typeNz*/*zapplication/octet-stream)rg   r‰   )r=   r   rf   rg   Zsupported_media_typesrÅ   Úparser_classrÆ   r   r   r   r¦   3  s    zAutoSchema.get_encoding)N)rA   rB   rC   rv   r<   ra   rŸ   r    r¡   rÂ   r¢   r£   Ústaticmethodr¤   r¦   rD   r   r   r>   r   r—   V  s   &,3	
r—   c                       s*   e Zd ZdZd‡ fdd„	Zdd„ Z‡  ZS )	ÚManualSchemazV
    Allows providing a list of coreapi.Fields,
    plus an optional description.
    rw   Nc                    sN   t ƒ  ¡  tdurt dt¡ tdd„ |D ƒƒs8J dƒ‚|| _|| _|| _	dS )z•
        Parameters:

        * `fields`: list of `coreapi.Field` instances.
        * `description`: String description for view. Optional.
        NrV   c                 s   s   | ]}t |tjƒV  qd S r/   )r‚   r	   r³   rÃ   r   r   r   Ú	<genexpr>[  r   z(ManualSchema.__init__.<locals>.<genexpr>z2`fields` must be a list of coreapi.Field instances)
r;   r<   r	   rW   rX   r   ÚallÚ_fieldsÚ_descriptionÚ	_encoding)r=   r‡   r[   rž   r>   r   r   r<   P  s    
zManualSchema.__init__c                 C   s@   |r|  d¡r|dd … }tjt ||¡| ¡ | j| j| jd�S )Nr   r   r�   )	r¨   r	   r©   r   rª   rs   rÎ   rÌ   rÍ   )r=   r   rf   r^   r   r   r   ra   `  s    
ûzManualSchema.get_link)rw   N)rA   rB   rC   rv   r<   ra   rD   r   r   r>   r   rÉ   K  s   rÉ   c                   C   s    t durt dt¡ ttjtƒS )zIs CoreAPI Mode enabled?NrV   )r	   rW   rX   r   Ú
issubclassr   ZDEFAULT_SCHEMA_CLASSr—   r   r   r   r   Ú
is_enabledn  s    rÐ   )&rW   Úcollectionsr   Úurllibr   Z	django.dbr   Zdjango.utils.encodingr   Zrest_frameworkr   r   r   Zrest_framework.compatr	   r
   r   Zrest_framework.settingsr   Ú
generatorsr   Z
inspectorsr   Úutilsr   r   r&   r.   r1   rJ   Údictr9   rO   rP   ry   r—   rÉ   rÐ   r   r   r   r   Ú<module>   s.   	 W v#