3
>^D                 @   s  d 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
mZ ddlmZ ddlmZ dd	l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 ejdZ dd Z!dd Z"G dd de#Z$G dd de$Z%G dd de$Z&G dd de$Z'dS )zb
inspectors.py   # Per-endpoint view introspection

See schemas.__init__.py for package overview.
    N)OrderedDict)WeakKeyDictionary)models)
force_text
smart_text)parse)ugettext_lazy)
exceptionsserializers)coreapi
coreschemauritemplate)api_settings)
formatting   )is_list_viewz^[a-zA-Z][0-9A-Za-z_]*:c             C   sf  | 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rt	jtdd | jj D ||dS t| tjrt| j}t	j
|||dS t| tjrt	j}t| jdd }|d k	r|jj}t|tjrt	j}|||dS t| tjr4t	j||dS t| tjr`t	j
t	jt| j d||dS t| tj!rt	jt| j ||d	S t| tj"rt	j#||dS t| tj$tj%frt	j&||dS t| tj'rt	j||dS t| tj(rt	j||d
dS t| tj)rt	j||ddS t| tj*r6t	j||dS | j+j,ddkrXt	j||ddS t	j||dS )N )itemstitledescription)r   r   c             S   s   g | ]\}}|t |fqS  )field_to_schema).0keyvaluer   r   P/tmp/pip-build-8app2_gc/djangorestframework/rest_framework/schemas/inspectors.py
<listcomp>.   s   z#field_to_schema.<locals>.<listcomp>)Z
propertiesr   r   model)enum)r   r   r   date)r   r   formatz	date-timeZbase_templateztextarea.htmltextarea)-labelr   	help_text
isinstancer
   ListSerializerZ	ListFieldr   childr   ArrayZ	DictFieldZObject
Serializerr   fieldsr   ZManyRelatedFieldZchild_relationZPrimaryKeyRelatedFieldStringgetattrqueryset_metapkr   	AutoFieldIntegerZRelatedFieldZMultipleChoiceFieldEnumlistchoicesZChoiceFieldZBooleanFieldBooleanZDecimalFieldZ
FloatFieldNumberZIntegerFieldZ	DateFieldZDateTimeFieldZ	JSONFieldstyleget)fieldr   r   Zchild_schemaZrelated_field_schema
schema_clsr   model_fieldr   r   r   r      s    


r   c             C   sJ   t |tjrtd}nt |tjr,td}ntd}tdj|| jjdS )Nzunique integer valuezUUID stringzunique valuez'A {value_type} identifying this {name}.)
value_typename)r$   r   r/   _Z	UUIDFieldr    r-   verbose_name)r   r:   r;   r   r   r   get_pk_descriptionr   s    

r?   c               @   sX   e Zd ZdZdd Zdd Zdd Zedd	 Zej	d
d	 Zej
dd	 Zdd ZdS )ViewInspectorz[
    Descriptor class on APIView.

    Provide subclass for per-view schema generation
    c             C   s   t  | _d S )N)r   instance_schemas)selfr   r   r   __init__   s    zViewInspector.__init__c             C   s   || j kr| j | S || _| S )a%  
        Enables `ViewInspector` as a Python _Descriptor_.

        This is how `view.schema` knows about `view`.

        `__get__` is called when the descriptor is accessed on the owner.
        (That will be when view.schema is called in our case.)

        `owner` is always the owner class. (An APIView, or subclass for us.)
        `instance` is the view instance or `None` if accessed from the class,
        rather than an instance.

        See: https://docs.python.org/3/howto/descriptor.html for info on
        descriptor usage.
        )rA   view)rB   instanceownerr   r   r   __get__   s    

zViewInspector.__get__c             C   s   || j |< |d k	r||_d S )N)rA   rD   )rB   rE   otherr   r   r   __set__   s    
zViewInspector.__set__c             C   s   | j dk	std| j S )zView property.NzvSchema generation REQUIRES a view instance. (Hint: you accessed `schema` from the view class rather than an instance.))_viewAssertionError)rB   r   r   r   rD      s    zViewInspector.viewc             C   s
   || _ d S )N)rJ   )rB   r   r   r   r   rD      s    c             C   s
   d | _ d S )N)rJ   )rB   r   r   r   rD      s    c             C   s   t d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
        z.get_link() must be overridden.N)NotImplementedError)rB   pathmethodbase_urlr   r   r   get_link   s    zViewInspector.get_linkN)__name__
__module____qualname____doc__rC   rG   rI   propertyrD   setterdeleterrP   r   r   r   r   r@      s   	r@   c                   s~   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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                s$   t t| j  |dk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`
        N)superrX   rC   _manual_fields)rB   manual_fields)	__class__r   r   rC      s    zAutoSchema.__init__c             C   s   | j ||}|| j||7 }|| j||7 }|| j||7 }| j||}| j||}|rxtdd |D rx| j||}nd }| j||}|r|j	dr|dd  }t
jtj|||j |||dS )Nc             S   s   g | ]}|j dkqS )formbody)r]   r^   )location)r   r8   r   r   r   r      s    z'AutoSchema.get_link.<locals>.<listcomp>/r   )urlaction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   Linkurlparseurljoinlower)rB   rM   rN   rO   r)   r[   rc   r   r   r   r   rP      s$    
zAutoSchema.get_linkc             C   sf   | j }t|d|j }t||dj}|rD| j||j tjt|S | j|t|d|j |j S dS )z
        Determine a link description.

        This will be based on the method docstring if one exists,
        or else the class docstring.
        rb   N)	rD   r+   rq   rT   _get_description_sectionr   dedentr   Zget_view_description)rB   rM   rN   rD   method_nameZmethod_docstringr   r   r   rl      s    zAutoSchema.get_descriptionc             C   s   dd |j  D }d}ddi}xH|D ]@}tj|rP|jd\}}}	|	j ||< q$||  d| 7  < q$W tj}
||kr|| j S ||
kr|
| |kr||
|  j S |d j S )Nc             S   s   g | ]}|qS r   r   )r   liner   r   r   r     s    z7AutoSchema._get_description_section.<locals>.<listcomp>r   :
)
splitlinesheader_regexmatch	partitionstripr   ZSCHEMA_COERCE_METHOD_NAMES)rB   rD   headerr   linesZcurrent_sectionsectionsru   Z	seperatorZleadZcoerce_method_namesr   r   r   rr     s    

z#AutoSchema._get_description_sectionc             C   s"  | j }tt|dddd}g }xtj|D ]}d}d}tj}	i }
|dk	ry|jj|}W n tk
rp   d}Y nX |dk	r|j	rt
|j	}|dk	r|jrt
|j}n|dk	r|jrt||}t|dr|j|kr|j|
d< nt|tjrtj}	tj|dd|	f ||d	|
d
}|j| q*W |S )zs
        Return a list of `coreapi.Field` instances corresponding to any
        templated path variables.
        r,   Nr   r   lookup_value_regexpatternrM   T)r   r   )r<   r_   requiredschema)rD   r+   r   	variablesr   r*   r-   	get_field	Exceptionr>   r   r#   Zprimary_keyr?   hasattrZlookup_fieldr   r$   r   r/   r0   r   Fieldappend)rB   rM   rN   rD   r   r)   variabler   r   r9   kwargsr:   r8   r   r   r   rd     s<    


zAutoSchema.get_path_fieldsc             C   s   | j }|dkrg S t|ds g S y|j }W n2 tjk
r^   d}tjdj|jj	|| Y nX t
|tjrtjddd	tj d
gS t
|tjsg S g }xV|jj D ]H}|jst
|tjrq|jo|dk}tj|jd|t|d
}|j| qW |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^   T)r<   r_   r   r   r]   )r   r   r   )rD   r   r   r	   ZAPIExceptionwarningswarnr    r\   rQ   r$   r
   r%   r   r   r   r'   r(   r)   valuesZ	read_onlyZHiddenFieldr   
field_namer   r   )rB   rM   rN   rD   
serializerr)   r8   r   r   r   r   re   D  s>    
z AutoSchema.get_serializer_fieldsc             C   s<   | j }t|||sg S t|dd }|s*g S |j }|j|S )Npagination_class)rD   r   r+   r   get_schema_fields)rB   rM   rN   rD   Z
paginationZ	paginatorr   r   r   rf   w  s    z AutoSchema.get_pagination_fieldsc             C   s:   t | jdddkrdS t| jdr.| jjdkS |j dk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_backendsNFrb   r2   retrieveupdatepartial_updatedestroyr7   putpatchdelete)r2   r   r   r   r   )r7   r   r   r   )r+   rD   r   rb   rq   )rB   rM   rN   r   r   r   _allows_filters  s
    zAutoSchema._allows_filtersc             C   s<   | j ||sg S g }x"| jjD ]}|| j| j7 }qW |S )N)r   rD   r   r   )rB   rM   rN   r)   Zfilter_backendr   r   r   rg     s    zAutoSchema.get_filter_fieldsc             C   s   | j S )N)rZ   )rB   rM   rN   r   r   r   rh     s    zAutoSchema.get_manual_fieldsc             C   sB   |s| S t dd | D }x|D ]}|||j< q W t|j } | 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   | ]}|j |fV  qd S )N)r<   )r   fr   r   r   	<genexpr>  s    z+AutoSchema.update_fields.<locals>.<genexpr>)r   r<   r2   r   )r)   Zupdate_withZby_namer   r   r   r   ri     s    
zAutoSchema.update_fieldsc             C   sR   | j }dddh}t|dg }x0|D ](}t|dd}||kr>|S |dkr"dS q"W dS )	zN
        Return the 'encoding' parameter to use for a given endpoint.
        zapplication/jsonz!application/x-www-form-urlencodedzmultipart/form-dataparser_classes
media_typeNz*/*zapplication/octet-stream)rD   r+   )rB   rM   rN   rD   Zsupported_media_typesr   parser_classr   r   r   r   rk     s    
zAutoSchema.get_encoding)N)rQ   rR   rS   rT   rC   rP   rl   rr   rd   re   rf   r   rg   rh   staticmethodri   rk   __classcell__r   r   )r\   r   rX      s   ,3	rX   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.
    r   Nc                s>   t t| j  tdd |D s(td|| _|| _|| _dS )z
        Parameters:

        * `fields`: list of `coreapi.Field` instances.
        * `description`: String description for view. Optional.
        c             s   s   | ]}t |tjV  qd S )N)r$   r   r   )r   r   r   r   r   r     s    z(ManualSchema.__init__.<locals>.<genexpr>z2`fields` must be a list of coreapi.Field instancesN)rY   r   rC   allrK   _fields_description	_encoding)rB   r)   r   rc   )r\   r   r   rC     s
    zManualSchema.__init__c             C   s@   |r|j dr|dd  }tjtj|||j | j| j| jdS )Nr`   r   )ra   rb   rc   r)   r   )	rm   r   rn   ro   rp   rq   r   r   r   )rB   rM   rN   rO   r   r   r   rP     s    
zManualSchema.get_link)r   N)rQ   rR   rS   rT   rC   rP   r   r   r   )r\   r   r     s   r   c                   s    e Zd ZdZ fddZ  ZS )DefaultSchemaz?Allows overriding AutoSchema using DEFAULT_SCHEMA_CLASS settingc                sH   t t| j||}t|ts |S tj}t|ts8td| }||_	|S )NzTDEFAULT_SCHEMA_CLASS must be set to a ViewInspector (usually an AutoSchema) subclass)
rY   r   rG   r$   r   ZDEFAULT_SCHEMA_CLASS
issubclassr@   rK   rD   )rB   rE   rF   resultZinspector_classZ	inspector)r\   r   r   rG     s    
zDefaultSchema.__get__)rQ   rR   rS   rT   rG   r   r   r   )r\   r   r     s   r   )(rT   rer   collectionsr   weakrefr   Z	django.dbr   Zdjango.utils.encodingr   r   Zdjango.utils.six.moves.urllibr   ro   Zdjango.utils.translationr   r=   Zrest_frameworkr	   r
   Zrest_framework.compatr   r   r   Zrest_framework.settingsr   Zrest_framework.utilsr   utilsr   compilery   r   r?   objectr@   rX   r   r   r   r   r   r   <module>   s,   
WE   