U
    ڲgG<                     @   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m	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 dd ZG dd dZG dd deZedd ZG dd dZdd Zdd ZG dd dZG dd dZdS )a~  
The Request class is used as a wrapper around the standard request object.

The wrapped request then offers a richer API, in particular :

    - content automatically parsed according to `Content-Type` header,
      and available as `request.data`
    - full support of PUT method, including support for file uploads
    - form overloading of HTTP method, content type and content
    N)contextmanager)settings)HttpRequest	QueryDict)RawPostDataException)MultiValueDictparse_header_parameters)
exceptions)api_settingsc                 C   s   t | \}}|dkp|dkS )zC
    Return True if the media type is a valid form media type.
    !application/x-www-form-urlencodedmultipart/form-datar   )
media_typeZbase_media_typeparams r   :/tmp/pip-unpacked-wheel-11h17kvo/rest_framework/request.pyis_form_media_type   s    r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	override_methoda  
    A context manager that temporarily overrides the method on a request,
    additionally setting the `view.request` attribute.

    Usage:

        with override_method(view, request, 'POST') as request:
            ... # Do stuff with `view` and `request`
    c                 C   s$   || _ || _|| _t|dd | _d S )Naction)viewrequestmethodgetattrr   )selfr   r   r   r   r   r   __init__-   s    zoverride_method.__init__c                 C   s<   t | j| j| j_t| jdi }|| j | j_| jjS )N
action_map)clone_requestr   r   r   r   getlowerr   )r   r   r   r   r   	__enter__3   s    zoverride_method.__enter__c                 O   s   | j | j_ | j| j_d S N)r   r   r   )r   argskwargr   r   r   __exit__:   s    
zoverride_method.__exit__N)__name__
__module____qualname____doc__r   r   r#   r   r   r   r   r   "   s   
r   c                   @   s   e Zd ZdS )WrappedAttributeErrorN)r$   r%   r&   r   r   r   r   r(   ?   s   r(   c                  c   sJ   z
dV  W n: t k
rD   t } tt| d }|| d Y nX dS )z
    Used to re-raise AttributeErrors caught during authentication, preventing
    these errors from otherwise being handled by the attribute access protocol.
    N      )AttributeErrorsysexc_infor(   strwith_traceback)infoexcr   r   r   wrap_attributeerrorsC   s    
r2   c                   @   s   e Zd ZdZdS )Emptyz`
    Placeholder for unset attributes.
    Cannot use `None`, as that may be a valid value.
    N)r$   r%   r&   r'   r   r   r   r   r3   Q   s   r3   c                 C   s   t | |tk	S r    )r   r3   )objnamer   r   r   _hasattrY   s    r6   c                 C   s   t | j| j| j| j| jd}| j|_| j|_| j|_| j	|_	| j
|_
||_t| dr\| j|_t| drn| j|_t| dr| j|_t| dr| j|_t| dr| j|_t| dr| j|_t| dr| j|_|S )	z
    Internal helper method to clone a request, replacing with a different
    HTTP method.  Used for checking permissions against other methods.
    )r   parsersauthenticators
negotiatorparser_context_user_auth_authenticatoraccepted_rendereraccepted_media_typeversionversioning_scheme)Request_requestr7   r8   r9   r:   _data_files
_full_data_content_type_streamr   hasattrr;   r<   r=   r>   r?   r@   rA   )r   r   retr   r   r   r   ]   s6    






r   c                   @   s    e Zd ZdZdd Zdd ZdS )ForcedAuthenticationzy
    This authentication class is used if the test client or request factory
    forcibly authenticated the request.
    c                 C   s   || _ || _d S r    
force_userforce_token)r   rM   rN   r   r   r   r      s    zForcedAuthentication.__init__c                 C   s   | j | jfS r    rL   )r   r   r   r   r   authenticate   s    z!ForcedAuthentication.authenticateN)r$   r%   r&   r'   r   rO   r   r   r   r   rK   ~   s   rK   c                   @   s  e Zd ZdZd3ddZdd Zdd Zd	d
 Zedd Z	edd Z
edd Zedd Zedd Zejdd Zedd Zejdd Ze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ed+d, Zed-d. Zed/d0 Zd1d2 ZdS )4rB   ac  
    Wrapper allowing to enhance a standard `HttpRequest` instance.

    Kwargs:
        - request(HttpRequest). The original request instance.
        - parsers(list/tuple). The parsers to use for parsing the
          request content.
        - authenticators(list/tuple). The authenticators used to try
          authenticating the request's user.
    Nc           	      C   s   t |ts"td|jj|jj|| _|p.d| _|p8d| _	|pF| 
 | _|| _t| _t| _t| _t| _t| _| jd kr~i | _| | jd< |jptj| jd< t|dd }t|dd }|d k	s|d k	rt||}|f| _	d S )NzUThe `request` argument must be an instance of `django.http.HttpRequest`, not `{}.{}`.r   r   encodingZ_force_auth_userZ_force_auth_token)
isinstancer   AssertionErrorformat	__class__r%   r$   rC   r7   r8   _default_negotiatorr9   r:   r3   rD   rE   rF   rG   rH   rP   r   DEFAULT_CHARSETr   rK   )	r   r   r7   r8   r9   r:   rM   rN   Zforced_authr   r   r   r      s2     




zRequest.__init__c                 C   s   d| j j| j j| j|  f S )Nz<%s.%s: %s %r>)rT   r%   r$   r   Zget_full_pathr   r   r   r   __repr__   s    zRequest.__repr__c                 O   s   | S r    r   )clsr!   kwargsr   r   r   __class_getitem__   s    zRequest.__class_getitem__c                 C   s   t  S r    )r   Z!DEFAULT_CONTENT_NEGOTIATION_CLASSrW   r   r   r   rU      s    zRequest._default_negotiatorc                 C   s   | j j}|d|ddS )NCONTENT_TYPEZHTTP_CONTENT_TYPE )rC   METAr   )r   metar   r   r   content_type   s    zRequest.content_typec                 C   s   t | ds|   | jS )zS
        Returns an object that may be used to stream the request content.
        rH   )r6   _load_streamrH   rW   r   r   r   stream   s    
zRequest.streamc                 C   s   | j jS )zA
        More semantically correct name for request.GET.
        )rC   GETrW   r   r   r   query_params   s    zRequest.query_paramsc                 C   s   t | ds|   | jS )NrF   )r6   _load_data_and_filesrF   rW   r   r   r   data   s    
zRequest.datac              	   C   s*   t | ds$t  |   W 5 Q R X | jS )z
        Returns the user associated with the current request, as authenticated
        by the authentication classes provided to the request.
        r;   )rI   r2   _authenticater;   rW   r   r   r   user   s    
zRequest.userc                 C   s   || _ || j_dS )ak  
        Sets the user on the current request. This is necessary to maintain
        compatibility with django.contrib.auth where the user property is
        set in the login and logout functions.

        Note that we also set the user on Django's underlying `HttpRequest`
        instance, ensuring that it is available to any middleware in the stack.
        N)r;   rC   rh   r   valuer   r   r   rh      s    
c              	   C   s*   t | ds$t  |   W 5 Q R X | jS )z
        Returns any non-user authentication information associated with the
        request, such as an authentication token.
        r<   )rI   r2   rg   r<   rW   r   r   r   auth   s    
zRequest.authc                 C   s   || _ || j_dS )z
        Sets any non-user authentication information associated with the
        request, such as an authentication token.
        N)r<   rC   rk   ri   r   r   r   rk     s    c              	   C   s*   t | ds$t  |   W 5 Q R X | jS )z
        Return the instance of the authentication instance class that was used
        to authenticate the request, or `None`.
        r=   )rI   r2   rg   r=   rW   r   r   r   successful_authenticator  s    
z Request.successful_authenticatorc                 C   sf   t | dsb|  \| _| _| jr<| j | _| j| j n| j| _t| jrb| j	| j
_| j| j
_dS )z>
        Parses the request content into `self.data`.
        rD   N)r6   _parserD   rE   copyrF   updater   r`   POSTrC   _postFILESrW   r   r   r   re     s    


zRequest._load_data_and_filesc              	   C   sv   | j j}zt|d|dd}W n ttfk
r@   d}Y nX |dkrRd| _n | j jsd| j | _nt	| j
| _dS )zF
        Return the content body of the request, as a stream.
        CONTENT_LENGTHZHTTP_CONTENT_LENGTHr   N)rC   r^   intr   
ValueError	TypeErrorrH   Z_read_startedioBytesIObody)r   r_   content_lengthr   r   r   ra   (  s    

zRequest._load_streamc                    s   d t  fdd| jD S )zJ
        Return True if this requests supports parsing form data.
        )r   r   c                 3   s   | ]}|j  kV  qd S r    )r   ).0parserZ
form_mediar   r   	<genexpr>C  s     z1Request._supports_form_parsing.<locals>.<genexpr>)anyr7   rW   r   r}   r   _supports_form_parsing;  s    zRequest._supports_form_parsingc                 C   s8  | j }z
| j}W nB tk
rR   t| jds. |  rJ| jj| jjf Y S d}Y nX |dksd|dkr|rt|rt	d| jj
d}ni }t }||fS | j| | j}|st|z|||| j}W n8 tk
r   t	d| jj
d| _t | _| j| _ Y nX z|j|jfW S  tk
r2   t }||f Y S X dS )z
        Parse the request content, returning a two-tuple of (data, files)

        May raise an `UnsupportedMediaType`, or `ParseError` exception.
        rq   Nr]   rP   )r`   rb   r   rI   rC   r   rp   rr   r   r   	_encodingr   r9   Zselect_parserr7   r
   ZUnsupportedMediaTypeparser:   	ExceptionrD   rE   rF   rf   filesr+   )r   r   rb   Z
empty_dataZempty_filesr|   parsedr   r   r   rm   E  s<    


zRequest._parsec              	   C   sh   | j D ]T}z|| }W n  tjk
r8   |    Y nX |dk	r|| _|\| _| _ dS q|   dS )zi
        Attempt to authenticate the request using each authentication instance
        in turn.
        N)r8   rO   r
   ZAPIException_not_authenticatedr=   rh   rk   )r   ZauthenticatorZuser_auth_tupler   r   r   rg   y  s    
zRequest._authenticatec                 C   s:   d| _ tjrt | _nd| _tjr0t | _nd| _dS )z
        Set authenticator, user & authtoken representing an unauthenticated request.

        Defaults are None, AnonymousUser & None.
        N)r=   r   ZUNAUTHENTICATED_USERrh   ZUNAUTHENTICATED_TOKENrk   rW   r   r   r   r     s    zRequest._not_authenticatedc                 C   s:   z|  d}t||W S  tk
r4   |  | Y S X dS )z
        If an attribute does not exist on this instance, then we also attempt
        to proxy it to the underlying HttpRequest object.
        rC   N)__getattribute__r   r+   )r   attrrC   r   r   r   __getattr__  s
    
zRequest.__getattr__c                 C   s   t dd S )Nz~`request.DATA` has been deprecated in favor of `request.data` since version 3.0, and has been fully removed as of version 3.2.NotImplementedErrorrW   r   r   r   DATA  s    zRequest.DATAc                 C   s2   t | ds|   t| jr"| jS td| jjdS )NrD   r]   r   )r6   re   r   r`   rD   r   rC   r   rW   r   r   r   rp     s
    

zRequest.POSTc                 C   s   t | ds|   | jS )NrE   )r6   re   rE   rW   r   r   r   rr     s    
zRequest.FILESc                 C   s   t dd S )Nz`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` since version 3.0, and has been fully removed as of version 3.2.r   rW   r   r   r   QUERY_PARAMS  s    zRequest.QUERY_PARAMSc                    s    fdd| j _d S )Nc                      s    S r    r   r   rj   r   r   <lambda>      z0Request.force_plaintext_errors.<locals>.<lambda>)rC   Zis_ajaxri   r   r   r   force_plaintext_errors  s    zRequest.force_plaintext_errors)NNNN)r$   r%   r&   r'   r   rX   r[   rU   propertyr`   rb   rd   rf   rh   setterrk   rl   re   ra   r   rm   rg   r   r   r   rp   rr   r   r   r   r   r   r   rB      sT       













4



rB   )r'   rw   r,   
contextlibr   Zdjango.confr   Zdjango.httpr   r   Zdjango.http.requestr   Zdjango.utils.datastructuresr   Zdjango.utils.httpr	   Zrest_frameworkr
   Zrest_framework.settingsr   r   r   r   r(   r2   r3   r6   r   rK   rB   r   r   r   r   <module>   s(   
	
!