B
    `R                 @   sH  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZyd dlZW n e	k
r`   d dlZY nX d dl
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mZmZ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#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3m4Z4m5Z5m6Z6 d dl7m8Z8 d d	l9m:Z:m;Z;m<Z<m=Z= d
ddgZ>G dd dZ?e? Z@dZAdZBG dd
 d
eCZDG dd deDZEG dd deCZFG dd deFeDZGdd ZHd,ddZIG dd deJZKG dd dejLZMdd ZNeNe_OG d d! d!ejLZPd"d# ZQd-d$d%ZRd&d' ZSd(d) ZTG d*d+ d+eCZUdS ).    N)accept_charset_propertyaccept_encoding_propertyaccept_language_propertyaccept_property)CacheControlserialize_cache_control)PY2bytes_native_parse_qsl_textreraise	text_type
url_encode	url_quoteurl_unquote
quote_plusurlparsecgi_FieldStorage)RequestCookies)
CHARSET_RE	SCHEME_RE	converterconverter_dateenviron_getterenviron_decoder
parse_auth	parse_intparse_int_safeparse_rangeserialize_authserialize_if_rangeserialize_intserialize_rangeupath_property)IfRangeAnyETagNoETagetag_property)EnvironHeaders)NestedMultiDict	MultiDictNoVarsGetDictBaseRequestRequestLegacyRequestc               @   s   e Zd Zdd ZdS )
_NoDefaultc             C   s   dS )Nz(No Default) )selfr1   r1   U/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/webob/request.py__repr__P   s    z_NoDefault.__repr__N)__name__
__module____qualname__r4   r1   r1   r1   r3   r0   O   s   r0   z/~!$&'()*+,;=:@)asciizlatin-1latinlatin_1l1latin1z
iso-8859-1	iso8859_1
iso_8859_1iso88598859c               @   s8  e Zd ZdZdZdddZedfddZdddZe	d	d
 Z
e
jdd
 Z
dddZdZe	dd Zejdd Zejdd ZedZe	dd ZeddZedZeddZedZeedddeedZed dZed!dZed"dZed#d$Zed%Zeed&e edZ!e"d'd$d(d)Z#e"d*d(d)Z$e#Z%e$Z&ed+d$Z'd,d- Z(dd.d/Z)e	e(e)e)e(j*Z+dZ,d0d1 Z-d2d3 Z.e	e-e.e-j*d4Z/e	d5d6 Z0e	d7d8 Z1e	d9d: Z2e	d;d< Z3e	d=d> Z4e	d?d@ Z5e	dAdB Z6e	dCdD Z7ddFdGZ8ddHdIZ9dJdK Z:dLdM Z;dNdO Z<dPdQ Z=e	e;e<e=e;j*d4Z>dRdS Z?dTdU Z@dVdW ZAe	e?e@eAe?j*ZBe	dXdY ZCdZd[ ZDd\d] ZEd^d_ ZFe	eDeEeFeDj*d4ZGe	d`da ZHe	dbdc ZIeIjdddc ZIeIjdedc ZIdfdg ZJdhdi ZKdjdk ZLe	eJeKeL ZMZNdldm ZOdndo ZPdpdq ZQe	eOePeQeOj*d4ZRe	drds ZSe	dtdu ZTdvdw ZUe	dxdy ZVe	dzd{ ZWeWjd|d{ ZWd}d~ ZXdd ZYeddEZZe	dd Z[e[jdd Z[dd Z\dd Z]dd Z^dddZ_e` Zaeb Zced Zeef ZgeedddeheiZjdd Zkdd Zldd Zmdd Zne	ekelemekj*d4ZoepdeqdZrepdesddEdZteuedddZveuedddZweuedddZxeedddeyjze{dZ|eeddde edZ}edddZ~eedddeedZedddZeZedddZdd ZdddZdd ZeZedd Zedd Zedd ZdddZdZdddZeZdd ZedddÄZdS )r-   i (  Nc       
      K   s   t |tk	rtd|f |d k	r4td|f t |d k	rNtd|f t t|sbtd| | j}||d< |r| j}d|kr|	d| _
x:| D ].\}}	t||std||	f t| ||	 qW d S )Nz*WSGI environ must be a dict; you passed %rzYou unicode_errors=%r to the Request constructor.  Passing a ``unicode_errors`` value to the Request is no longer supported in WebOb 1.2+.  This value has been ignored zYou passed decode_param_names=%r to the Request constructor. Passing a ``decode_param_names`` value to the Request is no longer supported in WebOb 1.2+.  This value has been ignored zYou passed charset=%r to the Request constructor. As of WebOb 1.2, if your application needs a non-UTF-8 request charset, please construct the request without a charset or with a charset of 'None',  then use ``req = req.decode(charset)``environmethodzUnexpected keyword: %s=%r)typedict	TypeErrorwarningswarnDeprecationWarning_is_utf8__dict__	__class__poprB   itemshasattrsetattr)
r2   rA   charsetunicode_errorsZdecode_param_nameskwdclsnamevaluer1   r1   r3   __init__c   s8    
zBaseRequest.__init__c             C   sf   | j ||}|tkrt|||kr*|S |s2|S t| |}trJ||S |tkrV|S t|d|S )Nzlatin-1)	rA   get	NoDefaultKeyErrorgetattrr   decode_LATIN_ENCODINGSr	   )r2   keydefaultencattrvalencodingr1   r1   r3   encget   s    

zBaseRequest.encgetc             C   sD   |rt | |}nd}tr*t||| j|< nt||d| j|< d S )Nr8   zlatin-1)r[   r   r	   rA   r\   )r2   r^   ra   r`   rb   r1   r1   r3   encset   s    zBaseRequest.encsetc             C   s,   | j d kr&t| j}t|r d}|| _ | j S )NzUTF-8)_charsetdetect_charset_content_type_rawrI   )r2   rP   r1   r1   r3   rP      s    

zBaseRequest.charsetc             C   s&   t |rd}|| jkr"td| d S )NzUTF-8zUse req = req.decode(%r))rI   rP   rH   )r2   rP   r1   r1   r3   rP      s    
strictc       
      C   s   |p| j }|dkr| S t||}td| j}| j}| j| j |	| j
|d}|dkrtt|	t| j|_|S |dkr|S | j }|dd d|d	< trt| j|d
d}nt| j|d
||d}|||j}	|	|_|	 |_|	d |S )NzUTF-8z; charset="UTF-8")query_stringcontent_typez!application/x-www-form-urlencodedzmultipart/form-dataCONTENT_LENGTH0 QUERY_STRINGT)fprA   keep_blank_values)ro   rA   rp   rb   errorsr   )rP   
Transcoderr   subrg   rj   rK   rA   copytranscode_queryri   r	   r
   body
setdefaultr   r   	body_filetranscode_fstellcontent_lengthseek)
r2   rP   rq   tZnew_content_typerj   r
fs_environfsfoutr1   r1   r3   r\      sB    






zBaseRequest.decode   c             C   sn   | j st S | j}| j}| jsj|dk	rj| j}|dd\}}||k	rft||}t	|}||f|d< |}|S )z
            Input stream of the request (wsgi.input).
            Setting this property resets the content_length and seekable flag
            (unlike setting req.body_file_raw).
        Nzwebob._body_file)r   r   )
is_body_readableioBytesIObody_file_rawr{   is_body_seekablerA   rX   LimitedLengthFileBufferedReader)r2   r~   clenenvwrappedrawr1   r1   r3   rx      s    

zBaseRequest.body_filec             C   s.   t |trtdd | _|| _d| _d| _d S )Nz$Excepted fileobj but received bytes.FT)
isinstancebytes
ValueErrorr{   r   r   r   )r2   rV   r1   r1   r3   rx     s    
c             C   s
   d| _ d S )N    )rv   )r2   r1   r1   r3   rx     s    z
wsgi.inputc             C   s   | j s|   | jS )a  
            Get the body of the request (wsgi.input) as a seekable file-like
            object. Middleware and routing applications should use this
            attribute over .body_file.

            If you access this value, CONTENT_LENGTH will also be updated.
        )r   make_body_seekabler   )r2   r1   r1   r3   body_file_seekable"  s    	zBaseRequest.body_file_seekablezwebob.url_encodingzUTF-8zwsgi.url_schemeREQUEST_METHODGETSERVER_PROTOCOLrk   z14.13intZREMOTE_USERZREMOTE_HOSTREMOTE_ADDRrn   rm   SERVER_NAMESERVER_PORTSCRIPT_NAMEurl_encoding)r`   	PATH_INFOCONTENT_TYPEc             C   s   | j ddd S )aU  Return the content type, but leaving off any parameters (like
        charset, but also things like the type in ``application/atom+xml;
        type=entry``)

        If you set this property, you can include parameters, or if
        you don't include any parameters in the value then existing
        parameters will be preserved.
        ;   r   )rg   split)r2   r1   r1   r3   _content_type__getH  s    	zBaseRequest._content_type__getc             C   sH   |d k	r>t |}d|kr>| j}d|kr>|d|ddd  7 }|| _d S )Nr   r   )strrg   r   )r2   rV   rj   r1   r1   r3   _content_type__setR  s    zBaseRequest._content_type__setc             C   s   | j dkrt| j| _ | j S )z_
        All the request headers as a case-insensitive dictionary-like
        object.
        N)_headersr(   rA   )r2   r1   r1   r3   _headers__getb  s    
zBaseRequest._headers__getc             C   s   | j   | j | d S )N)headersclearupdate)r2   rV   r1   r1   r3   _headers__setk  s    
zBaseRequest._headers__set)docc             C   s:   | j }|d}|dk	r,|dd  }n
|d}|S )a_  
        The effective client IP address as a string.  If the
        ``HTTP_X_FORWARDED_FOR`` header exists in the WSGI environ, this
        attribute returns the client IP address present in that header
        (e.g. if the header value is ``192.168.1.1, 192.168.1.2``, the value
        will be ``192.168.1.1``). If no ``HTTP_X_FORWARDED_FOR`` header is
        present in the environ at all, this attribute will return the value
        of the ``REMOTE_ADDR`` header.  If the ``REMOTE_ADDR`` header is
        unset, this attribute will return the value ``None``.

        .. warning::

           It is possible for user agents to put someone else's IP or just
           any string in ``HTTP_X_FORWARDED_FOR`` as it is a normal HTTP
           header. Forward proxies can also provide incorrect values (private
           IP addresses etc).  You cannot "blindly" trust the result of this
           method to provide you with valid data unless you're certain that
           ``HTTP_X_FORWARDED_FOR`` has the correct values.  The WSGI server
           must be behind a trusted proxy for this to be true.
        ZHTTP_X_FORWARDED_FORN,r   r   )rA   rX   r   strip)r2   eZxffaddrr1   r1   r3   client_addrq  s    

zBaseRequest.client_addrc             C   sf   | j }|d}|dk	rZd|kr>|d dkr>|dd\}}qb|d }|dkrTd	}qbd
}n|d }|S )a`  
        The effective server port number as a string.  If the ``HTTP_HOST``
        header exists in the WSGI environ, this attribute returns the port
        number present in that header. If the ``HTTP_HOST`` header exists but
        contains no explicit port number: if the WSGI url scheme is "https" ,
        this attribute returns "443", if the WSGI url scheme is "http", this
        attribute returns "80" .  If no ``HTTP_HOST`` header is present in
        the environ at all, this attribute will return the value of the
        ``SERVER_PORT`` header (which is guaranteed to be present).
        	HTTP_HOSTN:]r   zwsgi.url_schemehttps44380r   )rA   rX   rsplit)r2   r   hostport
url_schemer1   r1   r3   	host_port  s    
zBaseRequest.host_portc             C   s   | j }|d}|d }|d}|dk	rVd|krP|d dkrP|dd\}}qjd}n|d	}|d
}|dkr|dkrd}n|dkr|dkrd}||7 }|r|d| 7 }|S )z4
        The URL through the host (no path)
        zwsgi.url_schemez://r   Nr   r   r   r   r   r   r   r   httpr   z:%s)rA   rX   r   )r2   r   schemeurlr   r   r1   r1   r3   host_url  s(    



zBaseRequest.host_urlc             C   s   t | j| j}| jt|t S )zN
        The URL including SCRIPT_NAME (no PATH_INFO or query string)
        )r	   script_namer   r   r   	PATH_SAFE)r2   Zbscript_namer1   r1   r3   application_url  s    zBaseRequest.application_urlc             C   s   t | j| j}| jt|t S )zS
        The URL including SCRIPT_NAME and PATH_INFO, but not QUERY_STRING
        )r	   	path_infor   r   r   r   )r2   Z
bpath_infor1   r1   r3   path_url  s    zBaseRequest.path_urlc             C   s0   t | j| j}t | j| j}t|tt|t S )zG
        The path of the request, without host or query string
        )r	   r   r   r   r   r   )r2   Zbscriptbpathr1   r1   r3   path  s    zBaseRequest.pathc             C   s&   | j }| jd}|r"|d| 7 }|S )zM
        The path of the request, without host but with query string
        rn   ?)r   rA   rX   )r2   r   qsr1   r1   r3   path_qs  s
    zBaseRequest.path_qsc             C   s&   | j }| jd}|r"|d| 7 }|S )z>
        The full request URL, including QUERY_STRING
        rn   r   )r   rA   rX   )r2   r   r   r1   r1   r3   r     s
    zBaseRequest.urlFc             C   s0   |r| j }|ds$|d7 }n| j}t||S )z
        Resolve other_url relative to the request URL.

        If ``to_application`` is True, then resolve it relative to the
        URL with only SCRIPT_NAME
        /)r   endswithr   r   urljoin)r2   Z	other_urlZto_applicationr   r1   r1   r3   relative_url  s    

zBaseRequest.relative_urlc             C   s   | j }|sdS d}x"|dr4|d7 }|dd }qW |d}|dkrPt|}|d| }|dkspt||r|  j|| 7  _||d | _ |S dS )a  
        'Pops' off the next segment of PATH_INFO, pushing it onto
        SCRIPT_NAME, and returning the popped segment.  Returns None if
        there is nothing left on PATH_INFO.

        Does not return ``''`` when there's an empty segment (like
        ``/path//path``); these segments are just ignored.

        Optional ``pattern`` argument is a regexp to match the return value
        before returning. If there is no match, no changes are made to the
        request and None is returned.
        Nrm   r   r   r   )r   
startswithfindlenrematchr   )r2   patternr   Zslashesidxr~   r1   r1   r3   path_info_pop  s    
zBaseRequest.path_info_popc             C   s(   | j }|sdS |d}|ddd S )z
        Returns the next segment on PATH_INFO, or None if there is no
        next segment.  Doesn't modify the environment.
        Nr   r   r   )r   lstripr   )r2   r   r1   r1   r3   path_info_peek!  s
    
zBaseRequest.path_info_peekc             C   sF   d| j kr| j d S d| j kr,| j d d S i }d|f| j d< |S dS )z
        Return any *named* variables matched in the URL.

        Takes values from ``environ['wsgiorg.routing_args']``.
        Systems like ``routes`` set this value.
        zpaste.urlvarszwsgiorg.routing_argsr   r1   N)rA   )r2   resultr1   r1   r3   _urlvars__get,  s    


zBaseRequest._urlvars__getc             C   sT   | j }d|kr2|d d |f|d< d|krP|d= nd|krD||d< nd|f|d< d S )Nzwsgiorg.routing_argsr   zpaste.urlvarsr1   )rA   )r2   rV   rA   r1   r1   r3   _urlvars__set<  s    
zBaseRequest._urlvars__setc             C   sP   d| j kr| j d= d| j krL| j d d s4| j d= n| j d d i f| j d< d S )Nzpaste.urlvarszwsgiorg.routing_argsr   )rA   )r2   r1   r1   r3   _urlvars__delH  s    


zBaseRequest._urlvars__delc             C   s    d| j kr| j d d S dS dS )z
        Return any *positional* variables matched in the URL.

        Takes values from ``environ['wsgiorg.routing_args']``.
        Systems like ``routes`` set this value.
        zwsgiorg.routing_argsr   r1   N)rA   )r2   r1   r1   r3   _urlargs__getW  s    
zBaseRequest._urlargs__getc             C   sL   | j }d|kr||df}n"d|kr8||d d f}n|i f}||d< d S )Nzpaste.urlvarszwsgiorg.routing_argsr   )rA   rL   )r2   rV   rA   Zrouting_argsr1   r1   r3   _urlargs__sete  s    zBaseRequest._urlargs__setc             C   s>   d| j kr:| j d d s"| j d= nd| j d d f| j d< d S )Nzwsgiorg.routing_argsr   r1   )rA   )r2   r1   r1   r3   _urlargs__delq  s    

zBaseRequest._urlargs__delc             C   s   | j dddkS )aE  Is X-Requested-With header present and equal to ``XMLHttpRequest``?

        Note: this isn't set by every XMLHttpRequest request, it is
        only set if you are using a Javascript library that sets it
        (or you set the header yourself manually).  Currently
        Prototype and jQuery are known to set this header.ZHTTP_X_REQUESTED_WITHrm   ZXMLHttpRequest)rA   rX   )r2   r1   r1   r3   is_xhr~  s    zBaseRequest.is_xhrc             C   s"   d| j kr| j d S d| j  S dS )z>Host name provided in HTTP_HOST, with fall-back to SERVER_NAMEr   z%(SERVER_NAME)s:%(SERVER_PORT)sN)rA   )r2   r1   r1   r3   
_host__get  s    

zBaseRequest._host__getc             C   s   || j d< d S )Nr   )rA   )r2   rV   r1   r1   r3   
_host__set  s    zBaseRequest._host__setc             C   s   d| j kr| j d= d S )Nr   )rA   )r2   r1   r1   r3   
_host__del  s    
zBaseRequest._host__delc             C   s.   | j }d|kr*|d dkr*|ddd }|S )a   Returns the domain portion of the host value.  Equivalent to:

        .. code-block:: python

           domain = request.host
           if ':' in domain and domain[-1] != ']': # Check for ] because of IPv6
               domain = domain.rsplit(':', 1)[0]

        This will be equivalent to the domain portion of the ``HTTP_HOST``
        value in the environment if it exists, or the ``SERVER_NAME`` value in
        the environment if it doesn't.  For example, if the environment
        contains an ``HTTP_HOST`` value of ``foo.example.com:8000``,
        ``request.domain`` will return ``foo.example.com``.

        Note that this value cannot be *set* on the request.  To set the host
        value use :meth:`webob.request.Request.host` instead.
        r   r   r   r   r   )r   r   )r2   domainr1   r1   r3   r     s    zBaseRequest.domainc             C   s0   | j s
dS |   | j| j}| jd |S )z9
        Return the content of the request body.
        r   r   )r   r   rx   readr{   r   r|   )r2   r~   r1   r1   r3   rv     s    zBaseRequest.bodyc             C   sF   |d krd}t |ts&tdt| t|| _t|| _d| _	d S )Nr   z/You can only set Request.body to bytes (not %r)T)
r   r   rE   rC   r   r{   r   r   r   r   )r2   rV   r1   r1   r3   rv     s    

c             C   s
   d| _ d S )Nr   )rv   )r2   r1   r1   r3   rv     s    c             C   s   t | j| jS )z&Access the body of the request as JSON)jsonloadsrv   r\   rP   )r2   r1   r1   r3   _json_body__get  s    zBaseRequest._json_body__getc             C   s   t j|dd| j| _d S )N)r   r   )
separators)r   dumpsencoderP   rv   )r2   rV   r1   r1   r3   _json_body__set  s    zBaseRequest._json_body__setc             C   s   | ` d S )N)rv   )r2   r1   r1   r3   _json_body__del  s    zBaseRequest._json_body__delc             C   s    | j std| j}|| j S )z4
        Get/set the text value of the body
        z4You cannot access Request.text unless charset is set)rP   AttributeErrorrv   r\   )r2   rv   r1   r1   r3   
_text__get  s
    zBaseRequest._text__getc             C   s:   | j stdt|ts(tdt| || j | _d S )Nz5You cannot access Response.text unless charset is setz:You can only set Request.text to a unicode string (not %s))rP   r   r   r   rE   rC   r   rv   )r2   rV   r1   r1   r3   
_text__set  s    
zBaseRequest._text__setc             C   s   | ` d S )N)rv   )r2   r1   r1   r3   
_text__del  s    zBaseRequest._text__delc             C   s   | j }d|kr(|d \}}|| jkr(|S | j}| jdkr<|rD|dkrPtd| S |   |   | jd | }|	dd d|d	< t
rt| j|d
d}nt| j|d
dd}t|}|| jf|d< |S )a#  
        Return a MultiDict containing all the variables from a form
        request. Returns an empty dict-like object for non-form requests.

        Form requests are typically POST requests, however any other
        requests with an appropriate Content-Type are also supported.
        zwebob._parsed_post_varsPOST)rm   z!application/x-www-form-urlencodedzmultipart/form-dataz.Not an HTML form submission (Content-Type: %s)r   rk   rl   rm   rn   T)ro   rA   rp   utf8)ro   rA   rp   rb   )rA   r   rj   rB   r+   _check_charsetr   r|   rt   rw   r   r   rx   r*   Zfrom_fieldstorage)r2   r   varsrx   rj   r   r   r1   r1   r3   r     s<    	


zBaseRequest.POSTc             C   s\   | j }|dd}d|kr2|d \}}||kr2|S g }|rBt|}t||}||f|d< |S )z`
        Return a MultiDict containing all the variables from the
        QUERY_STRING.
        rn   rm   zwebob._parsed_query_vars)rA   rX   r   r,   )r2   r   sourcer   r   datar1   r1   r3   r      s    
zBaseRequest.GETc             C   s"   | j dkrtd| j | j f d S )NzUTF-8zhRequests are expected to be submitted in UTF-8, not %s. You can fix this by doing req = req.decode('%s'))rP   rH   )r2   r1   r1   r3   r   9  s    
zBaseRequest._check_charsetc             C   s   t | j| j}|S )zy
        A dictionary-like object containing both the parameters from
        the query string and request body.
        )r)   r   r   )r2   paramsr1   r1   r3   r   A  s    zBaseRequest.paramsc             C   s
   t | jS )zI
        Return a dictionary of cookies as found in the request.
        )r   rA   )r2   r1   r1   r3   cookiesJ  s    zBaseRequest.cookiesc             C   s&   | j dd  t| j }|| d S )NZHTTP_COOKIE)rA   rL   r   r   )r2   ra   r~   r1   r1   r3   r   Q  s    
c             C   s(   |    | j }| |}|  |S )zw
        Copy the request and environment object.

        This only does a shallow copy, except of wsgi.input
        )r   rA   rt   rK   	copy_body)r2   r   Znew_reqr1   r1   r3   rt   W  s
    

zBaseRequest.copyc             C   s   | j  }| j|ddddS )z
        Copies the request and environment object, but turning this request
        into a GET along the way.  If this was a POST request (or any other
        verb) then it becomes GET, and the request body is thrown away.
        r   Nr   )rB   rj   rv   )rA   rt   rK   )r2   r   r1   r1   r3   copy_getc  s    

zBaseRequest.copy_getzwebob.is_body_seekablec             C   s>   | j }|dk	r|dkrdS |dkr:| jd| jddS dS )z
        webob.is_body_readable is a flag that tells us that we can read the
        input stream even though CONTENT_LENGTH is missing.
        Nr   Tzwsgi.input_terminatedzwebob.is_body_readableF)r{   rA   rX   )r2   r   r1   r1   r3   r   q  s    zBaseRequest.is_body_readablec             C   s   t || jd< d S )Nzwsgi.input_terminated)boolrA   )r2   flagr1   r1   r3   r     s    c             C   s    | j r| jd n|   dS )a  
        This forces ``environ['wsgi.input']`` to be seekable.
        That means that, the content is copied into a BytesIO or temporary
        file and flagged as seekable, so that it will not be unnecessarily
        copied again.

        After calling this method the .body_file is always seeked to the
        start of file and .content_length is not None.

        The choice to copy to BytesIO is made from
        ``self.request_body_tempfile_limit``
        r   N)r   r   r|   r   )r2   r1   r1   r3   r     s    zBaseRequest.make_body_seekablec             C   s  | j r| jr| jd | j}| jdk	r0| jnd}d}d}| j}x|dkr|t|d}|sn| jdkrnP n|s~t	d| |r|
| n*||7 }t||kr|  }|
| d}| jdk	rD|t|8 }qDW |r| | _|d || _d| _d| _ n|| _nd| _dS )z
        Copies the body, in cases where it might be shared with another request
        object and that is not desired.

        This copies the body either into a BytesIO object (through setting
        req.body) or a temporary file.
        r   Ni  r   z1Client disconnected (%s more bytes were expected)T)r   r   r   r|   request_body_tempfile_limitr{   rx   r   minDisconnectionErrorwriter   make_tempfilerz   rv   )r2   Ztempfile_limittodoZnewbodyfileobjinputr   r1   r1   r3   r     s@    	





zBaseRequest.copy_bodyc             C   s   t  S )z
            Create a tempfile to store big request body.
            This API is not stable yet. A 'size' argument might be added.
        )tempfileTemporaryFile)r2   r1   r1   r3   r    s    zBaseRequest.make_tempfileTc             C   sb   g }|r|ddg7 }|r"| d |r0| d |r>| d x|D ]}|| jkrD| j|= qDW dS )a*  
        Remove headers that make the request conditional.

        These headers can cause the response to be 304 Not Modified,
        which in some cases you may not want to be possible.

        This does not remove headers like If-Match, which are used for
        conflict detection.
        HTTP_IF_RANGE
HTTP_RANGEHTTP_IF_NONE_MATCHHTTP_IF_MODIFIED_SINCEZHTTP_ACCEPT_ENCODINGN)appendrA   )r2   Zremove_encodingZremove_rangeZremove_matchZremove_modifiedZ
check_keysr^   r1   r1   r3   remove_conditional_headers  s    




z&BaseRequest.remove_conditional_headersZHTTP_AUTHORIZATIONz14.8c             C   sX   | j }|dd}|dd\}}|dk	r6||kr6|S tj|| jdd}||f|d< |S )z
        Get/set/modify the Cache-Control header (`HTTP spec section 14.9
        <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9>`_)
        HTTP_CACHE_CONTROLrm   zwebob._cache_control)NNNrequest)Z
updates_torC   )rA   rX   r   parse_update_cache_control)r2   r   rV   Zcache_headerZ	cache_objr1   r1   r3   _cache_control__get#  s    zBaseRequest._cache_control__getc             C   sd   | j }|pd}t|tr$t|dd}t|trLt|}||d< ||f|d< nt||d< d|d< d S )Nrm   r  )rC   r  zwebob._cache_control)NN)rA   r   rD   r   r   )r2   rV   r   Z	str_valuer1   r1   r3   _cache_control__set3  s    

zBaseRequest._cache_control__setc             C   s&   | j }d|kr|d= d|kr"|d= d S )Nr  zwebob._cache_control)rA   )r2   r   r1   r1   r3   _cache_control__del@  s
    zBaseRequest._cache_control__delc             C   s   t || jd< d S )Nr  )r   rA   )r2   Z	prop_dictr1   r1   r3   r  G  s    z!BaseRequest._update_cache_controlZHTTP_IF_MATCHz14.24r
  z14.26)strongZ	HTTP_DATEr  z14.25ZHTTP_IF_UNMODIFIED_SINCEz14.28r  z14.27zIfRange objectZHTTP_MAX_FORWARDSz14.31ZHTTP_PRAGMAz14.32r	  z14.35zRange objectZHTTP_REFERERz14.36ZHTTP_USER_AGENTz14.43c             C   sL   yd| j | jf }W n tk
r,   d}Y nX d| jjtt| |f }|S )Nz%s %sz(invalid WSGI environ)z<%s at 0x%x %s>)rB   r   rZ   rK   r5   absid)r2   rU   msgr1   r1   r3   r4   m  s    
zBaseRequest.__repr__c       	      C   s   | j }| j}||st|t|d }td| j|| jf g}d}| jr|dkrzt| j	|krvtdt| j	 }nd}|s| j	}x4t
| j D ]"\}}td||f }|| qW |r|d|g d|S )	z
            Return HTTP bytes representing this request.
            If skip_body is True, exclude the body.
            If skip_body is an integer larger than one, skip body
            only if its length is bigger than that number.
        Nz%s %s %sr   z<body skipped (len=%s)>Fz%s: %sr   s   
)r   r   r   AssertionErrorr   r	   rB   http_versionr   rv   sortedr   rM   r  extendjoin)	r2   Z	skip_bodyr   r   partsrv   kvheaderr1   r1   r3   as_bytesw  s&    zBaseRequest.as_bytesc             C   s   |   }|| jS )N)r"  r\   rP   )r2   r   r1   r1   r3   as_text  s    zBaseRequest.as_textc             C   s0   t |}| |}| t|kr,td|S )z
            Create a request from HTTP bytes data. If the bytes contain
            extra data after the request, raise a ValueError.
        z+The string contains more data than expected)r   r   	from_filerz   r   r   )rT   bfr~   r1   r1   r3   
from_bytes  s
    

zBaseRequest.from_bytesc             C   s   t |d}| |S )Nzutf-8)r	   r'  )rT   sr%  r1   r1   r3   	from_text  s    
zBaseRequest.from_textc             C   sJ  |  }t|t}|r d}d}nd}d}y>||}|dd\}}}	t|d}t|d}t|	d}	W n  tk
r   td| Y nX | t||	| d	}
|
j	d
= xd|  }|
 sP ||d\}}t|d}t|d
 }||
jkr|
j| d | }||
j|< qW |
j}|dkr&| }n
||}|r@t|d}||
_|
S )a  Read a request from a file-like object (it must implement
        ``.read(size)`` and ``.readline()``).

        It will read up to the end of the request, not the end of the
        file (unless the request is a POST or PUT and has no
        Content-Length, in that case, the entire file is read).

        This reads the request as represented by ``str(req)``; it may
        not read every valid HTTP request properly.
        z
r   s   
   :Nr   zutf-8zBad HTTP request line: %r)r  rB   r   r   z, )readliner   r   rstripr   r
   r   environ_from_urlupperrA   r   r   r{   r   r	   rv   )rT   ro   Z
start_lineZis_textZcrlfcolonr!  rB   resourcer  r~   linehnameZhvalr   rv   r1   r1   r3   r$    sJ    









zBaseRequest.from_filec          	      s   | j r| jd g  g d fdd	}|| j|}s@ shz| W dt|drb|  X }r d  d | d fS  d  d |fS dS )	a  
        Call the given WSGI application, returning ``(status_string,
        headerlist, app_iter)``

        Be sure to call ``app_iter.close()`` if it's there.

        If catch_exc_info is true, then returns ``(status_string,
        headerlist, app_iter, exc_info)``, where the fourth item may
        be None, but won't be if there was an exception.  If you don't
        do this and there was an exception, the exception will be
        raised directly.
        r   Nc                s,   |d k	rst | | ||g d d < jS )N)r   r  )statusr   exc_info)capturedcatch_exc_infooutputr1   r3   start_response  s    z4BaseRequest.call_application.<locals>.start_responsecloser   r   )N)r   r   r|   rA   r  rN   r9  )r2   applicationr6  r8  app_iterr1   )r5  r6  r7  r3   call_application  s    

zBaseRequest.call_applicationc             C   sV   |dkr|   }|r.| j|dd\}}}}~n| j|dd\}}}| j|t||dS )a  
        Like ``.call_application(application)``, except returns a
        response object with ``.status``, ``.headers``, and ``.body``
        attributes.

        This will use ``self.ResponseClass`` to figure out the class
        of the response object to return.

        If ``application`` is not given, this will send the request to
        ``self.make_default_send_app()``
        NT)r6  F)r3  Z
headerlistr;  )make_default_send_appr<  ResponseClasslist)r2   r:  r6  r3  r   r;  r4  r1   r1   r3   send  s    zBaseRequest.sendc             C   s4   yt }W n$ tk
r,   ddlm} |a Y nX |jS )Nr   )client)Z_client	NameErrorZwebobrA  Zsend_request_app)r2   rA  r1   r1   r3   r=  (  s    
z!BaseRequest.make_default_send_appc             K   s,  t |}|rt|\}}	}}
}|
s(|r4td| |r@||d< |	rd|	kr||dkr^|	d7 }	n|dkrp|	d7 }	ntd| |	dd	\}}||d
< ||d< |	|d< |rt||d< |r|| |d|d}|rd|kr|d }|dk	r||d< t|||d | |f|}|dk	r(|j	| |S )a(  
        Create a blank request environ (and Request wrapper) with the
        given path (path should be urlencoded), and any keys from
        environ.

        The path will become path_info, with any query string split
        off and used.

        All necessary keys will be added to the environ, but the
        values you pass in will take precedence.  If you pass in
        base_url then wsgi.url_scheme, HTTP_HOST, and SCRIPT_NAME will
        be filled in from that value.

        Any extra keyword will be passed to ``__init__``.
        z-base_url (%r) cannot have a query or fragmentzwsgi.url_schemer   r   z:80r   z:443zUnknown scheme: %rr   r   r   r   r   rj   r   zContent-TypeN)rj   )
r-  r   urlsplitr   r   r   r   rX   environ_add_POSTr   )rT   r   rA   base_urlr   r   rR   r   r   netlocqueryfragmentr   r   rj   objr1   r1   r3   blank1  sF    




zBaseRequest.blank)NNN)N)Nrh   )N)F)N)TTTT)F)F)NF)NNNN)r5   r6   r7   r   re   rW   rY   rc   rd   propertyrP   setterr\   _setattr_stacklevelrx   deleterr   r   r   r   r   rB   r  r   r   r!   r{   Zremote_userZremote_hostremote_addrri   Zserver_namer   Zserver_portr   r   r   uscript_name
upath_inforg   r   r   __doc__rj   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Zurlvarsr   r   r   Zurlargsr   r   r   r   r   r   rv   r   r   r   r   Z	json_bodyr   r   r   textr   r   r   r   r   rt   r   r   r   r   r   r  r  r   acceptr   Zaccept_charsetr   accept_encodingr   Zaccept_languager   r   authorizationr  r  r  r  Zcache_controlr'   r%   Zif_matchr&   Zif_none_matchr   dateZif_modified_sinceZif_unmodified_sincer$   r  r    Zif_rangeZmax_forwardsZpragmar   r"   rangeZrefererZreferrer
user_agentr4   r"  r#  __str__classmethodr'  r)  r$  r<  r>  r@  Zget_responser=  rJ  r1   r1   r1   r3   r-   [   s8   
2

	
/ 












			






2	
S   









"8
$
	 c               @   s*   e Zd ZedZedZedfddZdS )r/   r   r   Nc             C   s.   | j ||}|tkrt|||kr*|S |S )N)rA   rX   rY   rZ   )r2   r^   r_   r`   ra   r1   r1   r3   rc   l  s    zLegacyRequest.encget)r5   r6   r7   r#   rP  rQ  rY   rc   r1   r1   r1   r3   r/   h  s   c               @   s:   e Zd ZdZe fddZe fddZe fddZdS )	AdhocAttrMixin   c             C   sB   t | j|||k	s|dr,t| || n|| jdi |< d S )N_zwebob.adhoc_attrs)r[   rK   r   object__setattr__rA   rw   )r2   attrrV   DEFAULTr1   r1   r3   r`  w  s    
zAdhocAttrMixin.__setattr__c             C   s0   y| j d | S  tk
r*   t|Y nX d S )Nzwebob.adhoc_attrs)rA   rZ   r   )r2   ra  rb  r1   r1   r3   __getattr__~  s    zAdhocAttrMixin.__getattr__c             C   sP   t | j|||k	rt| |S y| jd |= W n tk
rJ   t|Y nX d S )Nzwebob.adhoc_attrs)r[   rK   r_  __delattr__rA   rZ   r   )r2   ra  rb  r1   r1   r3   rd    s    zAdhocAttrMixin.__delattr__N)r5   r6   r7   rM  r_  r`  rc  rd  r1   r1   r1   r3   r\  t  s   r\  c               @   s   e Zd ZdZdS )r.   z$ The default request implementation N)r5   r6   r7   rR  r1   r1   r1   r3   r.     s   c             C   s   t | rxt| \}}} }}|r.td| |r>| d| 7 } d|kr|dkrX|d7 }q|dkrj|d7 }qtd| nd}d	}| rd| kr| dd
\}}t|}nt| }d}dd|pd||dd |dd
 |dd|t t	j
dddd}|S )Nz#Path cannot contain a fragment (%r)r   r   r   z:80r   z:443zUnknown scheme: %rzlocalhost:80r   rm   r   r   zHTTP/1.0)r   r   F)r   r   r   rn   r   r   r   r   zwsgi.versionzwsgi.url_schemez
wsgi.inputzwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_once)r   searchr   rC  rE   r   r   r   r   sysstderr)r   r   rF  r   rH  r   ri   r   r1   r1   r3   r-    sF    



r-  c             C   s.  |d krd S t |tr |d}| d dkr4d| d< d}t|drtt| }x$|D ]\}}t |ttfrTd}P qTW |d kr|rd}nd	}|drt |tst	||\}}nD|d	r|rt
d
| t |tst|}nt |tst
d| t|d}t|| d< d| d< tt|| d< || d< d S )Nr8   r   )r   PUTr   FrM   Tzmultipart/form-dataz!application/x-www-form-urlencodedz4Submiting files is not allowed for content type `%s`z9Please provide `POST` data as bytes for content type `%s`r   z
wsgi.inputzwebob.is_body_seekablerk   r   )r   r   r   rN   r?  rM   tupler   r   _encode_multipartr   r   r	   r   r   r   r   )r   r   rj   Z	has_filesr  r   r1   r1   r3   rD    sD    









rD  c               @   s   e Zd ZdS )r   N)r5   r6   r7   r1   r1   r1   r3   r     s   r   c               @   s8   e Zd Zdd Zdd Zdd Zedd Zd	d
 ZdS )r   c             C   s   || _ || _|| _d S )N)filemaxlen	remaining)r2   rk  rl  r1   r1   r3   rW     s    zLimitedLengthFile.__init__c             C   s   d| j j| j| jf S )Nz<%s(%r, maxlen=%s)>)rK   r5   rk  rl  )r2   r1   r1   r3   r4     s    zLimitedLengthFile.__repr__c             C   s
   | j  S )N)rk  fileno)r2   r1   r1   r3   rn    s    zLimitedLengthFile.filenoc               C   s   dS )NTr1   r1   r1   r1   r3   readable  s    zLimitedLengthFile.readablec             C   sj   | j s
dS tt|| j }| j|}t|}|  j |8  _ ||k rZ| j rZtd| j f ||d |< |S )Nr   zLThe client disconnected while sending the body (%d more bytes were expected))rm  r   r   rk  r   r   )r2   buffZsz0r   szr1   r1   r3   readinto  s    zLimitedLengthFile.readintoN)	r5   r6   r7   rW   r4   rn  staticmethodro  rr  r1   r1   r1   r3   r     s
   r   c             C   s*   | j rd| j| jf S d| j| j| jf S )z monkey patch for FieldStorage.__repr__

    Unbelievably, the default __repr__ on FieldStorage reads
    the entire file content instead of being sane about it.
    This is a simple replacement that doesn't do that
    zFieldStorage(%r, %r)zFieldStorage(%r, %r, %r))rk  rU   filenamerV   )r2   r1   r1   r3   _cgi_FieldStorage__repr__patch  s    ru  c               @   s8   e Zd Zdd Zdd Zdd Zedd Zd	d
 ZdS )FakeCGIBodyc             C   s@   t dt |dr*t|s*td| || _|| _d | _d S )NzFakeCGIBody is no longer used by WebOb and will be removed from a future version of WebOb. If you require FakeCGIBody please make a copy into you own projectzmultipart/form-dataz*Content-type: %r does not contain boundary)	rF   rG   rH   r   _get_multipart_boundaryr   r   rj   rk  )r2   r   rj   r1   r1   r3   rW     s    
zFakeCGIBody.__init__c             C   sL   t | j}t|dkr2|d d d |dd   }d| jjtt| |f S )N      z...z<%s at 0x%x viewing %s>)reprr   r   rK   r5   r  r  )r2   innerr1   r1   r3   r4   -  s    
zFakeCGIBody.__repr__c             C   s   d S )Nr1   )r2   r1   r1   r3   rn  5  s    zFakeCGIBody.filenoc               C   s   dS )NTr1   r1   r1   r1   r3   ro  8  s    zFakeCGIBody.readablec             C   s   | j d kr| jdrBddd | j D }tt|| _ nL| jdr|t	| j | jt dd | _ | j 
d ndstd	| j | j |S )
Nz!application/x-www-form-urlencoded&c             s   s2   | ]*\}}d t t|dt t|df V  qdS )z%s=%sr   N)r   r	   ).0r  r   r1   r1   r3   	<genexpr>@  s   z'FakeCGIBody.readinto.<locals>.<genexpr>zmultipart/form-data)r   r   r   zBad content type: %r)rk  rj   r   r  r   rM   r   r   r	   rj  r|   r  rr  )r2   rp  r   r1   r1   r3   rr  <  s    

zFakeCGIBody.readintoN)	r5   r6   r7   rW   r4   rn  rs  ro  rr  r1   r1   r1   r3   rv    s
   rv  c             C   s,   t d| t j}|r(t|ddS d S )Nzboundary=([^ ]+)r   ")r   re  Ir
   groupr   )ctypemr1   r1   r3   rw  R  s    rw  c                s  |p
t  }|j  fdd}d}t|}|sNtttd}|d| 7 }xl| D ]b\}} d ||  | |d |dk	r|d	|  d}	t	|d
dr|j
}	n(t|ttfr|\}	}t|dr| }|	dk	r|d|	  t|	d }
nd}
 | t	|ddr`|d|j  |jrVx,t|j D ]\}}|d||f  q8W  | n|
rz|d|
   |  | t|dr|j}t|tr | n||  | qVW |d|  |r||fS || fS dS )z-Encode a multipart request body into a stringc                s    |  d d S )Nr   )r   )r}   )wr1   r3   wt[  s    z_encode_multipart.<locals>.wts   

   z; boundary=%ss   --zContent-Disposition: form-dataNz; name="%s"rt  r   z; filename="%s"r   rC   zContent-type: %sz	; %s="%s"rV   z--%s--)r   r   r  rw  r
   binasciihexlifyosurandomr[   rt  r   r?  ri  rN   r   	mimetypes
guess_typerC   type_optionsr  rM   rV   r   getvalue)r   rj   r   r&  r  CRLFboundaryrU   rV   rt  Z	mime_typeZct_nameZct_valuer1   )r  r3   rj  W  s^    


rj  c             C   s&   t | }|r"|dd S d S )Nr   r  )r   re  r  r   )r  r  r1   r1   r3   rf     s    
rf   c             C   s    | sdS |   dddkS d S )NT-rm   r   )lowerreplace)rP   r1   r1   r3   rI     s    rI   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
rr   rh   c                s     | _ | _ fdd| _d S )Nc                s   |   dS )Nr   )r\   r   )r%  )rP   rq   r1   r3   <lambda>  r   z%Transcoder.__init__.<locals>.<lambda>)rP   rq   _trans)r2   rP   rq   r1   )rP   rq   r3   rW     s    zTranscoder.__init__c                sT   |}d|kr|S t r<t|| j}| j  fdd|D }ntt|| j}t|S )N=c                s    g | ]\}} | |fqS r1   r1   )r~  r  r   )r}   r1   r3   
<listcomp>  s    z.Transcoder.transcode_query.<locals>.<listcomp>)r   r   	parse_qslrP   r  r?  r   r   )r2   qZq_origr1   )r}   r3   ru     s    zTranscoder.transcode_queryc                s   t r fdd}ndd }g }xX|jp(dD ]J}||j|_|jr^||j|_||j|f q*||j||jf q*W t||t d\}}|S )Nc                s    | d k	r|   j jS | S d S )N)r\   rP   rq   )r%  )r2   r1   r3   r\     s    z'Transcoder.transcode_fs.<locals>.decodec             S   s   | S )Nr1   )r%  r1   r1   r3   r\     s    r1   )r   )	r   r?  rU   rt  r  rV   rj  r   r   )r2   r   rj   r\   r   fieldr   r1   )r2   r3   ry     s    zTranscoder.transcode_fsN)rh   )r5   r6   r7   rW   ru   ry   r1   r1   r1   r3   rr     s   
rr   )N)N)Vr  r   r  r   rf  r  r  Z
simplejsonr   ImportErrorrF   Zwebob.acceptparser   r   r   r   Zwebob.cachecontrolr   r   Zwebob.compatr   r	   r
   r   r   r   r   r   r   r   r   r   Zwebob.cookiesr   Zwebob.descriptorsr   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   Z
webob.etagr$   r%   r&   r'   Zwebob.headersr(   Zwebob.multidictr)   r*   r+   r,   __all__r0   rY   r   r]   r_  r-   r/   r\  r.   r-  rD  IOErrorr   	RawIOBaser   ru  r4   rv  rw  rj  rf   rI   rr   r1   r1   r1   r3   <module>   sd   8D
          ,
+$6
;