B
    `                 @   s  d dl Z d dlZd dl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mZmZmZmZ d dlmZmZ d d	lmZ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)m*Z*m+Z+m,Z, d dl-m.Z. d dl/m0Z0 d dl1m2Z2m3Z3m4Z4 yd dl5Z6W n e7k
r>   d dl6Z6Y nX dgZ8e 9de j:Z;e 9de j:Z<dZ=e> Z?G dd de>Z@d+ddZAd,ddZBG dd de>ZCG dd de>ZDG dd de>ZEdd  ZFd!d" ZGd#d$ ZHd%d& ZId'd( ZJd)d* ZKdS )-    N)	b64encode)datetime	timedelta)md5)ContentRange)CacheControlserialize_cache_control)PY2bytes_native_string_types	text_type	url_quoteurlparse)Cookiemake_cookie)parse_date_deltaserialize_date_deltatimedelta_to_seconds)
CHARSET_RE	SCHEME_RE	converterdate_headerheader_getterlist_header
parse_authparse_content_rangeparse_etag_response	parse_intparse_int_safeserialize_authserialize_content_rangeserialize_etag_responseserialize_int)ResponseHeaders)BaseRequest)status_generic_reasonsstatus_reasonswarn_deprecationResponsez(([a-z0-9]+)=(?:"([^"]*)"|([a-z0-9_.-]*))z^[a-z0-9_.-]+$s
        c            
   @   s4  e Zd ZdZdZdZdZdZdZdZ	dZ
ddddddefddZed	d
 Zdd Zdd ZdddZdd Zdd ZeeeejdZdd Zdd Zeeeejd ZZdd Zdd Zdd ZeeeeejdZd d! Zd"d# ZeeeejdZ d$d% Z!dd'd(Z"ee!e"e"Z#d)d* Z$d+d, Z%d-d. Z&ee$e%e& Z'Z(d/d0 Z)ee)Z*d1d2 Z+d3d4 Z,d5d6 Z-ee+e,e-e+jdZ.ee+e,e-d7 Z/Z0d8d9 Z1d:d; Z2d<d= Z3ee1e2e3e1jdZ4d>d? Z5d@dA Z6dBdC Z7dDdE Z8ee6e7e8e6jdZ9e:dFdGZ;e:dHdIZ<e=e>dJdKe?e@dLZAe>dMdNZBe:dOdPZCe>dQdRZDe>dSdRZEe>dTdUZFe>dVdWZGe=e>dXdYeHeIdZZJeKd[d\ZLeKd]d^ZMeKd_d`ZNe>dadbZOe=eOePeQdcZReddde ZSe>dfdgZTe>dhdiZUe=e>djdkeVe@dLZWe=e>dldmeXeYdnZZe>dodpZ[e=e>dqdre\e]Z^dsdt Z_dudv Z`dwdx Zaee_e`eae_jdZbdydz Zcd{d| Zdd}d~ ZeeecedeeecjdZfdd Zgdd Zhdd ZieegeheiegjZjdddZkdddZldddZmdd ZndZodd Zpdd Zqdd Zrdd ZseepeqerepjdZtdddZuedd euZvdddZwdd ZxdddZyezdd Z{dd Z|dd Z}dZ~dd Zdd ZdS )r)   a  
    Represents a WSGI response.

    If no arguments are passed, creates a :class:`~Response` that uses a
    variety of defaults. The defaults may be changed by sub-classing the
    :class:`~Response`. See the :ref:`sub-classing notes
    <response_subclassing_notes>`.

    :cvar ~Response.body: If ``body`` is a ``text_type``, then it will be
        encoded using either ``charset`` when provided or ``default_encoding``
        when ``charset`` is not provided if the ``content_type`` allows for a
        ``charset``. This argument is mutually  exclusive with ``app_iter``.

    :vartype ~Response.body: bytes or text_type

    :cvar ~Response.status: Either an :class:`int` or a string that is
        an integer followed by the status text. If it is an integer, it will be
        converted to a proper status that also includes the status text.  Any
        existing status text will be kept. Non-standard values are allowed.

    :vartype ~Response.status: int or str

    :cvar ~Response.headerlist: A list of HTTP headers for the response.

    :vartype ~Response.headerlist: list

    :cvar ~Response.app_iter: An iterator that is used as the body of the
        response. Should conform to the WSGI requirements and should provide
        bytes. This argument is mutually exclusive with ``body``.

    :vartype ~Response.app_iter: iterable

    :cvar ~Response.content_type: Sets the ``Content-Type`` header. If no
        ``content_type`` is provided, and there is no ``headerlist``, the
        ``default_content_type`` will be automatically set. If ``headerlist``
        is provided then this value is ignored.

    :vartype ~Response.content_type: str or None

    :cvar conditional_response: Used to change the behavior of the
        :class:`~Response` to check the original request for conditional
        response headers. See :meth:`~Response.conditional_response_app` for
        more information.

    :vartype conditional_response: bool

    :cvar ~Response.charset: Adds a ``charset`` ``Content-Type`` parameter. If
        no ``charset`` is provided and the ``Content-Type`` is text, then the
        ``default_charset`` will automatically be added.  Currently the only
        ``Content-Type``'s that allow for a ``charset`` are defined to be
        ``text/*``, ``application/xml``, and ``*/*+xml``. Any other
        ``Content-Type``'s will not have a ``charset`` added. If a
        ``headerlist`` is provided this value is ignored.

    :vartype ~Response.charset: str or None

    All other response attributes may be set on the response by providing them
    as keyword arguments. A :exc:`TypeError` will be raised for any unexpected
    keywords.

    .. _response_subclassing_notes:

    **Sub-classing notes:**

    * The ``default_content_type`` is used as the default for the
      ``Content-Type`` header that is returned on the response. It is
      ``text/html``.

    * The ``default_charset`` is used as the default character set to return on
      the ``Content-Type`` header, if the ``Content-Type`` allows for a
      ``charset`` parameter. Currently the only ``Content-Type``'s that allow
      for a ``charset`` are defined to be: ``text/*``, ``application/xml``, and
      ``*/*+xml``. Any other ``Content-Type``'s will not have a ``charset``
      added.

    * The ``unicode_errors`` is set to ``strict``, and access on a
      :attr:`~Response.text` will raise an error if it fails to decode the
      :attr:`~Response.body`.

    * ``default_conditional_response`` is set to ``False``. This flag may be
      set to ``True`` so that all ``Response`` objects will attempt to check
      the original request for conditional response headers. See
      :meth:`~Response.conditional_response_app` for more information.

    * ``default_body_encoding`` is set to 'UTF-8' by default. It exists to
      allow users to get/set the ``Response`` object using ``.text``, even if
      no ``charset`` has been set for the ``Content-Type``.
    z	text/htmlzUTF-8strictFNc             K   sx  |d kr^|d kr^d|ks d|kr^d|kr4| d}	n
| d}	tj|	ddd}|d kr^d}|d krt|d krd}n|d k	rtd|d krd	| _n|| _d | _|d krg | _n|| _d }
|t	k	r|}
| jd
 dko| jd d dk}|p| j
}|d krp|rp|rpd|k}|rd }
|
}|s:|t	kr:| jr:| j}|r`|dksTt|r`|d| 7 }| jd|f |d kr| j| _n
t|| _|d kr|rt|tr|
p| j}
|
d krtd||
}|g}|d k	rdd | jD | jd d < | jdtt|f n|d kr,|s,dg}|| _x@| D ]4\}}t| j|sbtd||f t| || q<W d S )N	json_bodyjson),:)
separatorszUTF-8zapplication/json    z8You may only give one of the body and app_iter argumentsz200 OKr   1   )Z204Z205Z304zcharset=z	text/htmlz
; charset=zContent-Typez9You cannot set the body to a text value without a charsetc             S   s$   g | ]\}}|  d kr||fqS )zcontent-length)lower).0kv r7   V/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/webob/response.py
<listcomp>0  s   z%Response.__init__.<locals>.<listcomp>zContent-LengthzUnexpected keyword: %s=%r)popr,   dumpsencode	TypeError_statusstatus_headers_headerlist_markerdefault_content_typedefault_charset_content_type_has_charsetappenddefault_conditional_responseconditional_responsebool
isinstancer   charsetstrlen	_app_iteritemshasattr	__class__setattr)selfbodyr?   
headerlistapp_itercontent_typerH   rK   kwr+   encodingZcode_has_bodyhas_charsetnew_charsetnamevaluer7   r7   r8   __init__   s~     










zResponse.__init__c             C   s  g }|   }t|t}|r(d}d}nd}d}||r`|dd\}}}	dt|t|	f }xn|   }
|
stP y|
|d\}}W n  tk
r   td	|
 Y nX | }|t|d
t|d
f qbW | ||dd}|	|j
pd}|r||_n||_|S )ap  Reads a response from a file-like object (it must implement
        ``.read(size)`` and ``.readline()``).

        It will read up to the end of the response, not the end of the
        file.

        This reads the response as represented by ``str(resp)``; it
        may not read every valid HTTP response properly.  Responses
        must have a ``Content-Length``.r.   zHTTP/   :s   HTTP/N   z%s %s   zBad header line: %rzlatin-1r7   )r?   rU   rV   r   )readlinestriprJ   r   
startswithsplitr   
ValueErrorrF   readcontent_lengthtextrT   )clsfprU   r?   Zis_textZ_colonZ_httpZhttp_verZ
status_numZstatus_textlineheader_namer]   rrT   r7   r7   r8   	from_fileC  s@    

zResponse.from_filec             C   s>   t | j}t| j t || _| j| j| jdd || jdS )zMakes a copy of the response.N)r?   rU   rV   rH   )listrN   
iter_closerQ   r>   rA   rH   )rS   rV   r7   r7   r8   copyw  s    


zResponse.copyc             C   s   d| j jtt| | jf S )Nz<%s at 0x%x %s>)rQ   __name__absidr?   )rS   r7   r7   r8   __repr__  s    zResponse.__repr__c             C   sP   | j g}|s| j |tdj| j7 }|sF| jrF|dtr<| jn| jg7 }d|S )Nz%s: %s z
)r?   rT   map__mod__rU   r	   ri   join)rS   Z	skip_bodypartsr7   r7   r8   __str__  s    
zResponse.__str__c             C   s   | j S )z$
        The status string.
        )r>   )rS   r7   r7   r8   _status__get  s    zResponse._status__getc          	   C   s   yt |}W n ttfk
r$   Y nX || _d S tsJt|tr^|d}nt|tr^|	d}t|t
sxtdt| yt | d  W n tk
r   tdY nX || _d S )Nasciiz3You must set status to a string or integer (not %s)r   z&Invalid status code, integer required.)intrf   r=   status_coder	   rJ   bytesdecoder   r<   rL   typere   r>   )rS   r]   coder7   r7   r8   _status__set  s(    



zResponse._status__set)docc             C   s   t | j d S )z+
        The status as an integer.
        r   )r   r>   re   )rS   r7   r7   r8   _status_code__get  s    zResponse._status_code__getc             C   sF   yd|t | f | _W n* tk
r@   d|t|d  f | _Y nX d S )Nz%d %sd   )r'   r>   KeyErrorr&   )rS   r   r7   r7   r8   _status_code__set  s    zResponse._status_code__setc             C   s   | j S )z/
        The list of response headers.
        )rA   )rS   r7   r7   r8   _headerlist__get  s    zResponse._headerlist__getc             C   s4   d | _ t|ts*t|dr"| }t|}|| _d S )NrO   )r@   rJ   rp   rP   rO   rA   )rS   r]   r7   r7   r8   _headerlist__set  s    

zResponse._headerlist__setc             C   s
   g | _ d S )N)rU   )rS   r7   r7   r8   _headerlist__del  s    zResponse._headerlist__delc             C   s   | j dkrt| j| _ | j S )z:
        The headers in a dictionary-like object.
        N)r@   r$   Z	view_listrA   )rS   r7   r7   r8   _headers__get  s    
zResponse._headers__getc             C   s"   t |dr| }|| _d | _d S )NrO   )rP   rO   rU   r@   )rS   r]   r7   r7   r8   _headers__set  s    
zResponse._headers__setc             C   s   | j }t|tr$t|dkr$|d S |dkr4tdzd|}W dt| X t|trbt|||g| _ t|dkrxn:| j	dkrt|| _	n$| j	t|krt
d| j	t|f |S )z}
        The body of the response, as a :class:`bytes`.  This will read in
        the entire app_iter if necessary.
        ra   r   NzNo body has been setr0   z@Content-Length is different from actual app_iter length (%r!=%r))rN   rJ   rp   rM   AttributeErrorrz   rq   r   _error_unicode_in_app_iterrh   AssertionError)rS   rV   rT   r7   r7   r8   
_body__get  s(    



zResponse._body__getr0   c             C   sT   t |ts.t |trd}ndt| }t|| jd k	r>d | _|g| _t|| _d S )NzAYou cannot set Response.body to a text object (use Response.text)z3You can only set the body to a binary type (not %s))	rJ   r   r   r   r=   rN   content_md5rM   rh   )rS   r]   msgr7   r7   r8   
_body__set  s    



zResponse._body__setc             C   s   t | jdS )aB  
        Set/get the body of the response as JSON.

        .. note::

           This will automatically :meth:`~bytes.decode` the
           :attr:`~Response.body` as ``UTF-8`` on get, and
           :meth:`~str.encode` the :meth:`json.dumps` as ``UTF-8``
           before assigning to :attr:`~Response.body`.

        zUTF-8)r,   loadsrT   r   )rS   r7   r7   r8   _json_body__get1  s    zResponse._json_body__getc             C   s   t j|ddd| _d S )N)r-   r.   )r/   zUTF-8)r,   r;   r<   rT   )rS   r]   r7   r7   r8   _json_body__set@  s    zResponse._json_body__setc             C   s   | ` d S )N)rT   )rS   r7   r7   r8   _json_body__delC  s    zResponse._json_body__delc             C   s@   | j }t|tr0t|dkr0|d dkr,dS dS |dkr<dS dS )z
        Determine if the the response has a :attr:`~Response.body`. In
        contrast to simply accessing :attr:`~Response.body`, this method
        will **not** read the underlying :attr:`~Response.app_iter`.
        ra   r   r0   TFN)rN   rJ   rp   rM   )rS   rV   r7   r7   r8   _has_body__getH  s    zResponse._has_body__getc             C   s4   | j s| jstd| j p| j}| j}||| jS )z
        Get/set the text value of the body using the ``charset`` of the
        ``Content-Type`` or the ``default_body_encoding``.
        zNYou cannot access Response.text unless charset or default_body_encoding is set)rK   default_body_encodingr   rT   r   unicode_errors)rS   ZdecodingrT   r7   r7   r8   
_text__getb  s    zResponse._text__getc             C   sJ   | j s| jstdt|ts.tdt| | j p8| j}||| _d S )NzNYou cannot access Response.text unless charset or default_body_encoding is setz;You can only set Response.text to a unicode string (not %s))	rK   r   r   rJ   r   r=   r   r<   rT   )rS   r]   rY   r7   r7   r8   
_text__setp  s    
zResponse._text__setc             C   s   | ` d S )N)rT   )rS   r7   r7   r8   
_text__del}  s    zResponse._text__delzDeprecated alias for .textc             C   s   t | S )z
        A file-like object that can be used to write to the
        body.  If you passed in a list ``app_iter``, that ``app_iter`` will be
        modified by writes.
        )ResponseBodyFile)rS   r7   r7   r8   _body_file__get  s    zResponse._body_file__getc             C   s   t || _d S )N)	iter_filerV   )rS   filer7   r7   r8   _body_file__set  s    zResponse._body_file__setc             C   s   | ` d S )N)rT   )rS   r7   r7   r8   _body_file__del  s    zResponse._body_file__delc             C   s   t |tsFt |ts(d}t|t| | js:d}t||| j}| j}t |tszt| }| _W d t	| X |}t
dd |D | _|| | jd k	r|  jt|7  _d S )Nz6You can only write str to a Response.body_file, not %sz;You can only write text to Response if charset has been setc             s   s   | ]}t |V  qd S )N)rM   )r4   chunkr7   r7   r8   	<genexpr>  s    z!Response.write.<locals>.<genexpr>)rJ   r   r   r=   r   rK   r<   rN   rp   rq   sumrh   rF   rM   )rS   ri   r   rV   Znew_app_iterr7   r7   r8   write  s$    





zResponse.writec             C   s   | j S )z
        Returns the ``app_iter`` of the response.

        If ``body`` was set, this will create an ``app_iter`` from that
        ``body`` (a single-item list).
        )rN   )rS   r7   r7   r8   _app_iter__get  s    zResponse._app_iter__getc             C   s   | j d k	rd | _|| _ d S )N)rN   rh   )rS   r]   r7   r7   r8   _app_iter__set  s    
zResponse._app_iter__setc             C   s   g | _ d | _d S )N)rN   rh   )rS   r7   r7   r8   _app_iter__del  s    zResponse._app_iter__delZAllowz14.7ZVaryz14.44zContent-Lengthz14.17r   zContent-Encodingz14.11zContent-Languagez14.12zContent-Locationz14.14zContent-MD5zContent-Dispositionz19.5.1zAccept-Rangesz14.5zContent-Rangez14.16zContentRange objectDatez14.18ZExpiresz14.21zLast-Modifiedz14.29ETagz14.19z
Entity tagc             C   s   t | jddS )NT)strong)r   	_etag_raw)rS   r7   r7   r8   etag_strong  s    zResponse.etag_strongZLocationz14.30ZPragmaz14.32ZAgez14.6zRetry-Afterz14.37zHTTP date or delta secondsServerz14.38zWWW-Authenticatez14.47c             C   s0   | j d}|sdS t|}|r,|dS dS )z
        Get/set the ``charset`` specified in ``Content-Type``.

        There is no checking to validate that a ``content_type`` actually
        allows for a ``charset`` parameter.
        zContent-TypeNra   )headersgetr   searchgroup)rS   headermatchr7   r7   r8   _charset__get  s    

zResponse._charset__getc             C   sz   |d kr|    d S | jdd }|d kr2tdt|}|r`|d |  || d   }|d| 7 }|| jd< d S )NzContent-Typez:You cannot set the charset when no content-type is definedz; charset=%s)_charset__delr   r   r   r   r   startend)rS   rK   r   r   r7   r7   r8   _charset__set  s    
 zResponse._charset__setc             C   sV   | j dd }|d krd S t|}|rH|d |  || d   }|| j d< d S )NzContent-Type)r   r:   r   r   r   r   )rS   r   r   r7   r7   r8   r   #  s    
 zResponse._charset__delc             C   s$   | j d}|sdS |ddd S )a  
        Get/set the ``Content-Type`` header. If no ``Content-Type`` header is
        set, this will return ``None``.

        .. versionchanged:: 1.7

            Setting a new ``Content-Type`` will remove all ``Content-Type``
            parameters and reset the ``charset`` to the default if the
            ``Content-Type`` is ``text/*`` or XML (``application/xml`` or
            ``*/*+xml``).

            To preserve all ``Content-Type`` parameters, you may use the
            following code:

            .. code-block:: python

                resp = Response()
                params = resp.content_type_params
                resp.content_type = 'application/something'
                resp.content_type_params = params
        zContent-TypeN;ra   r   )r   r   re   )rS   r   r7   r7   r8   _content_type__get4  s    zResponse._content_type__getc             C   s   |s|    d S tr(t|tr(|d}t|ts:td|}d|k}d }|sZ| jrZ| j}|rz|dksnt|rz|d| 7 }|| j	d< d S )Nzlatin-1z1content_type requires value to be of string_typeszcharset=z	text/htmlz
; charset=zContent-Type)
_content_type__delr	   rJ   r   r<   r   r=   rD   rE   r   )rS   r]   rW   rZ   r[   r7   r7   r8   _content_type__setO  s$    

zResponse._content_type__setc             C   s   | j dd  d S )NzContent-Type)r   r:   )rS   r7   r7   r8   r   x  s    zResponse._content_type__delc             C   sh   | j dd}d|kri S |ddd }i }x4t|D ]&}|dpT|dpTd||d< q:W |S )z
        A dictionary of all the parameters in the content type.

        (This is not a view, set to change, modifications of the dict will not
        be applied otherwise.)
        zContent-Typerw   r   ra   r`   r2   )r   r   re   	_PARAM_REfinditerr   )rS   paramsresultr   r7   r7   r8   _content_type_params__get  s    &z"Response._content_type_params__getc             C   s   |s|    d S g }xDt| D ]4\}}t|sDd|dd }|d||f  q"W | jdd	ddd	 }|d
|7 }|| jd< d S )
Nz"%s""z\"z; %s=%szContent-Typerw   r   ra   r   )_content_type_params__delsortedrO   _OK_PARAM_REr   replacerF   r   r:   re   rz   )rS   Z
value_dictr   r5   r6   ctr7   r7   r8   _content_type_params__set  s    
z"Response._content_type_params__setc             C   s$   | j ddddd | j d< d S )NzContent-Typerw   r   ra   r   )r   r   re   )rS   r7   r7   r8   r     s    z"Response._content_type_params__delrw   /c             C   s   |	rt ddd |
r"| j|dd |s4t|	tr4|	}|spt|	trp|	jrd|	 rd|	|	  jdd}	|	t  }t	|d}t
|||||||||d		}| jd
|f dS )a  
        Set (add) a cookie for the response.

        Arguments are:

        ``name``

           The cookie name.

        ``value``

           The cookie value, which should be a string or ``None``.  If
           ``value`` is ``None``, it's equivalent to calling the
           :meth:`webob.response.Response.unset_cookie` method for this
           cookie key (it effectively deletes the cookie on the client).

        ``max_age``

           An integer representing a number of seconds, ``datetime.timedelta``,
           or ``None``. This value is used as the ``Max-Age`` of the generated
           cookie.  If ``expires`` is not passed and this value is not
           ``None``, the ``max_age`` value will also influence the ``Expires``
           value of the cookie (``Expires`` will be set to ``now`` +
           ``max_age``).  If this value is ``None``, the cookie will not have a
           ``Max-Age`` value (unless ``expires`` is set). If both ``max_age``
           and ``expires`` are set, this value takes precedence.

        ``path``

           A string representing the cookie ``Path`` value.  It defaults to
           ``/``.

        ``domain``

           A string representing the cookie ``Domain``, or ``None``.  If
           domain is ``None``, no ``Domain`` value will be sent in the
           cookie.

        ``secure``

           A boolean.  If it's ``True``, the ``secure`` flag will be sent in
           the cookie, if it's ``False``, the ``secure`` flag will not be
           sent in the cookie.

        ``httponly``

           A boolean.  If it's ``True``, the ``HttpOnly`` flag will be sent
           in the cookie, if it's ``False``, the ``HttpOnly`` flag will not
           be sent in the cookie.

        ``samesite``

          A string representing the ``SameSite`` attribute of the cookie or
          ``None``. If samesite is ``None`` no ``SameSite`` value will be sent
          in the cookie. Should only be ``"strict"``, ``"lax"``, or ``"none"``.

        ``comment``

           A string representing the cookie ``Comment`` value, or ``None``.
           If ``comment`` is ``None``, no ``Comment`` value will be sent in
           the cookie.

        ``expires``

           A ``datetime.timedelta`` object representing an amount of time,
           ``datetime.datetime`` or ``None``. A non-``None`` value is used to
           generate the ``Expires`` value of the generated cookie. If
           ``max_age`` is not passed, but this value is not ``None``, it will
           influence the ``Max-Age`` header. If this value is ``None``, the
           ``Expires`` cookie value will be unset (unless ``max_age`` is set).
           If ``max_age`` is set, it will be used to generate the ``expires``
           and this value is ignored.

           If a ``datetime.datetime`` is provided it has to either be timezone
           aware or be based on UTC. ``datetime.datetime`` objects that are
           local time are not supported. Timezone aware ``datetime.datetime``
           objects are converted to UTC.

           This argument will be removed in future versions of WebOb (version
           1.9).

        ``overwrite``

           If this key is ``True``, before setting the cookie, unset any
           existing cookie.

        zVArgument "expires" will be removed in a future version of WebOb, please use "max_age".g?ra   F)r*   N)tzinfozutf-8)max_agepathdomainsecurehttponlycommentsamesitez
Set-Cookie)r(   unset_cookierJ   r   r   r   	utcoffsetr   utcnowr
   r   rU   rF   )rS   r\   r]   r   r   r   r   r   r   expires	overwriter   cookier7   r7   r8   
set_cookie  s     ]


zResponse.set_cookiec             C   s   | j |d||d dS )z
        Delete a cookie from the client.  Note that ``path`` and ``domain``
        must match how the cookie was originally set.

        This sets the cookie to the empty string, and ``max_age=0`` so
        that it should expire immediately.
        N)r   r   )r   )rS   r\   r   r   r7   r7   r8   delete_cookie'  s    zResponse.delete_cookieTc             C   s   | j d}|s|sdS t }x|D ]}|| q$W t|trJ|d}||kr||= | j d= x6| D ]}| j	d|
 f qjW n|rtd| dS )zS
        Unset a cookie with the given name (remove it from the response).
        z
Set-CookieNutf8z'No cookie has been set with the name %r)r   getallr   loadrJ   r   r<   valuesrU   rF   	serializer   )rS   r\   r*   existingcookiesr   mr7   r7   r8   r   1  s    


zResponse.unset_cookiec                sh   | j dsS ttrBx"| j dD ]}j d| q(W S dd | jD   fdd}|S dS )zMerge the cookies that were set on this response with the
        given ``resp`` object (which can be any WSGI application).

        If the ``resp`` is a :class:`webob.Response` object, then the
        other object will be modified in-place.
        z
Set-Cookiec             S   s    g | ]}|d    dkr|qS )r   z
set-cookie)r3   )r4   hr7   r7   r8   r9   S  s    z*Response.merge_cookies.<locals>.<listcomp>c                s   d fdd	}| |S )Nc                s   | |  |dS )N)exc_infor7   )r?   r   r   )	c_headersstart_responser7   r8   repl_start_responseV  s    
zEResponse.merge_cookies.<locals>.repl_app.<locals>.repl_start_response)Nr7   )environr   r   )r   resp)r   r8   repl_appU  s    z(Response.merge_cookies.<locals>.repl_appN)r   r   rJ   r)   r   addrU   )rS   r   r   r   r7   )r   r   r8   merge_cookiesE  s    
zResponse.merge_cookiesc             C   sx   | j dd}| jdkr4tj|| jdd| _|| j_| jj|krrtj|dd}| jj  | jj	|j || j_| j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>`_).
        zcache-controlrw   Nresponse)Z
updates_tor   )r   )
r   r   _cache_control_objr   parse_update_cache_controlheader_value
propertiesclearupdate)rS   r]   Znew_objr7   r7   r8   _cache_control__getb  s    
zResponse._cache_control__getc             C   s~   |sd}t |trt|d}t |tr.t|}t |tr\| jd krP|| jd< d S t|d}| j}|j	
  |j	|j	 d S )Nrw   r   zCache-Control)rJ   dictr   r   rL   r   r   r   cache_controlr   r   r   )rS   r]   cacher7   r7   r8   _cache_control__sets  s    






zResponse._cache_control__setc             C   s
   i | _ d S )N)r   )rS   r7   r7   r8   _cache_control__del  s    zResponse._cache_control__delc             C   s.   t |}|s d| jkr*| jd= n
|| jd< d S )NzCache-Control)r   r   )rS   Z	prop_dictr]   r7   r7   r8   r     s
    

zResponse._update_cache_controlr   c             K   s   |dkrd}nt |tr t|}| j}|dkr0nx|s~d|_d|_d|_d|_d|_d|_	t
 | _d| jkrvt
 | _d| _n*|j  ||_t
 t|d | _d| _x | D ]\}}t||| qW dS )z
            Set expiration on this request.  This sets the response to
            expire in the given seconds, and any other attributes are used
            for ``cache_control`` (e.g., ``private=True``).
        Tr   Nzlast-modifiedzno-cache)seconds)rJ   r   r   r   no_storeno_cacheZmust_revalidater   Z
post_checkZ	pre_checkr   r   r   r   last_modifiedpragmar   r   rO   rR   )rS   r   rX   r   r\   r]   r7   r7   r8   _cache_expires  s0    




zResponse._cache_expiresc             C   s   | j S )N)r  )rS   r7   r7   r8   <lambda>  r0   zResponse.<lambda>gzipc             C   sz   |dkst d| |dkr(|   dS | jdkr6dS |rNt| j| _d| _n"tt| j| _tt	t
| j| _d| _dS )zt
        Encode the content with the given encoding (only ``gzip`` and
        ``identity`` are supported).
        )identityr  zUnknown encoding: %rr  Nr  )r   decode_contentcontent_encodinggzip_app_iterrN   rV   rh   rp   r   rx   rM   )rS   rY   Zlazyr7   r7   r8   encode_content  s    


zResponse.encode_contentc             C   s   | j pd}|dkrd S |dkr*td| |dkrxddlm} ddlm} |dd	|| jd
}| | _d | _ |  n@yt	
| j| _W n& t	jk
r   t	
| jd| _Y nX d | _ d S )Nr  )r  deflatez)I don't know how to decode the content %sr  r   )GzipFile)BytesIOrw   rn   )filenamemodefileobji)r
  rf   r  r  ior  rT   rg   closezlib
decompresserror)rS   r
  r  r  Zgzip_fr7   r7   r8   r	    s$    



zResponse.decode_contentc             C   sP   |dkr| j }t| }t|}|dd}t|}|d| _|rL|| _dS )a  
        Generate an etag for the response object using an MD5 hash of
        the body (the ``body`` parameter, or ``self.body`` if not given).

        Sets ``self.etag``.

        If ``set_content_md5`` is ``True``, sets ``self.content_md5`` as well.
        N   
r0   =)	rT   r   digestr   r   r   rc   etagr   )rS   rT   Zset_content_md5Z
md5_digestr7   r7   r8   md5_etag  s    	zResponse.md5_etagc             C   s"   t |r|S tt| |}|S )N)r   r   r   urljoin_request_uri)r   r]   Znew_locationr7   r7   r8   _make_location_absolute  s    
z Response._make_location_absolutec                s    fddj D S )Nc                s4   g | ],\}}|  d kr ||fn| |fqS )location)r3   r  )r4   r5   r6   )r   rS   r7   r8   r9     s   z,Response._abs_headerlist.<locals>.<listcomp>)rA   )rS   r   r7   )r   rS   r8   _abs_headerlist
  s    zResponse._abs_headerlistc             C   sD   | j r| ||S | |}|| j| |d dkr>t| jS | jS )z,
        WSGI application interface
        REQUEST_METHODHEAD)rH   conditional_response_appr!  r?   EmptyResponserN   )rS   r   r   rU   r7   r7   r8   __call__  s    

zResponse.__call__)GETr#  c       
      C   s  t |}| |}|dd}|| jkrzd}|jrF| jrF| j|jk}n|jr^| jr^| j|jk}|rz|dt| t	| j
S |jr| |jkr| jdkr|dkr| jdkr| jdk	r|j| j}|dkr:t| j
 td|j }d	tt|fd
ttdd| jfdgt| }|d| |dkr4dS |gS | |j|j}	|	dk	r|jdk	sdtd	t|j|j fd
t|fgt|d }|d| |dkrt	|	S |	S || j| |dkrt	| j
S | j
S )a  
        Like the normal ``__call__`` interface, but checks conditional headers:

            * ``If-Modified-Since``   (``304 Not Modified``; only on ``GET``,
              ``HEAD``)
            * ``If-None-Match``       (``304 Not Modified``; only on ``GET``,
              ``HEAD``)
            * ``Range``               (``406 Partial Content``; only on ``GET``,
              ``HEAD``)
        r"  r'  Fz304 Not ModifiedN)r#  r'     z#Requested range not satisfiable: %szContent-LengthzContent-Range)zContent-Typez
text/plainz#416 Requested Range Not Satisfiabler#  r7   )zcontent-lengthz206 Partial Content)r%   r!  r   _safe_methodsZif_none_matchr  Zif_modified_sincer  filter_headersr%  rN   rangeZif_rangecontent_ranger   rh   rq   r
   rL   rM   r   app_iter_ranger   stopr   r?   )
rS   r   r   reqrU   methodZ	status304r,  rT   rV   r7   r7   r8   r$  (  s^    














z!Response.conditional_response_appc             C   s(   | j }t|dr|||S t|||S )z
        Return a new ``app_iter`` built from the response ``app_iter``, that
        serves up only the given ``start:stop`` range.
        r-  )rN   rP   r-  AppIterRange)rS   r   r.  rV   r7   r7   r8   r-  m  s    
zResponse.app_iter_range)F)r0   )
rw   Nr   NFFNNFN)r   N)T)r   )r  F)NF)rs   
__module____qualname____doc__rC   rD   r   rG   r   requestr   rB   r^   classmethodro   rr   rv   r|   r}   r   propertyr?   r   r   r   Z
status_intr   r   r   rU   r   r   r   r   r   rT   r   r   r   r,   r+   r   has_bodyr   r   r   ri   Zunicode_bodyZubodyr   r   r   Z	body_filer   r   r   r   rV   r   Zallowvaryr   r   r   r#   rh   r
  Zcontent_languagecontent_locationr   content_dispositionZaccept_rangesr   r!   r,  r   dater   r  r   r   r"   r  r   r   r  r   Zager   r   retry_afterserverr   r    Zwww_authenticater   r   r   rK   r   r   r   rW   r   r   r   Zcontent_type_paramsr   r   r   r   r   r   r   r   r   r   r  Zcache_expiresr  r	  r  staticmethodr  r!  r&  r)  r$  r-  r7   r7   r7   r8   r)   <   s  X 4
$


	





















)   
u



$

Ezcontent-lengthzcontent-typec                s    fdd| D S )Nc                s    g | ]}|d     kr|qS )r   )r3   )r4   r   )remove_headersr7   r8   r9   y  s    z"filter_headers.<locals>.<listcomp>r7   )hlistrA  r7   )rA  r8   r*  x  s    r*     c             c   s    x|  |}|sP |V  qW d S )N)rg   )r   
block_sizedatar7   r7   r8   r   |  s
    
r   c               @   sT   e Zd ZdZdZdd Zdd Zedd d	d
Zdd Z	dd Z
dd Zdd ZdS )r   wbFc             C   s   || _ |j| _dS )zH
        Represents a :class:`~Response` as a file like object.
        N)r   r   )rS   r   r7   r7   r8   r^     s    zResponseBodyFile.__init__c             C   s
   d| j  S )Nz<body_file for %r>)r   )rS   r7   r7   r8   rv     s    zResponseBodyFile.__repr__c             C   s   | j jS )N)r   rK   )rS   r7   r7   r8   r    r0   zResponseBodyFile.<lambda>z:The encoding of the file (inherited from response.charset))r   c             C   s   x|D ]}|  | qW dS )z<
        Write a sequence of lines to the response.
        N)r   )rS   seqitemr7   r7   r8   
writelines  s    
zResponseBodyFile.writelinesc             C   s   t dd S )Nz Response bodies cannot be closed)NotImplementedError)rS   r7   r7   r8   r    s    zResponseBodyFile.closec             C   s   d S )Nr7   )rS   r7   r7   r8   flush  s    zResponseBodyFile.flushc             C   s"   | j jsdS tdd | j jD S )zS
        Provide the current location where we are going to start writing.
        r   c             S   s   g | ]}t |qS r7   )rM   )r4   r   r7   r7   r8   r9     s    z)ResponseBodyFile.tell.<locals>.<listcomp>)r   r8  r   rV   )rS   r7   r7   r8   tell  s    zResponseBodyFile.tellN)rs   r2  r3  r  closedr^   rv   r7  rY   rI  r  rK  rL  r7   r7   r7   r8   r     s   r   c               @   s<   e Zd ZdZdd Zdd Zdd Zdd	 ZeZd
d Z	dS )r1  zA
    Wraps an ``app_iter``, returning just a range of bytes.
    c             C   sX   |dkst d| |d ks8|dkr,||ks8t d| t|| _d| _|| _|| _d S )Nr   zBad start: %rzBad stop: %r)r   iterrV   _posr   r.  )rS   rV   r   r.  r7   r7   r8   r^     s    

zAppIterRange.__init__c             C   s   | S )Nr7   )rS   r7   r7   r8   __iter__  s    zAppIterRange.__iter__c             C   s   | j | j }}x| jD ]}|  jt|7  _| j|k r:qq| j|krHdS ||| j d  }|d k	r| j|kr|d || j  }t||| kst|S qW t d S )Nr0   )r   r.  rV   rO  rM   r   StopIteration)rS   r   r.  r   r7   r7   r8   _skip_start  s    

zAppIterRange._skip_startc             C   sx   | j | jk r|  S | j}|d k	r0| j |kr0tt| j}|  j t|7  _ |d ks^| j |krb|S |d || j   S d S )N)rO  r   rR  r.  rQ  nextrV   rM   )rS   r.  r   r7   r7   r8   rS    s    
zAppIterRange.nextc             C   s   t | j d S )N)rq   rV   )rS   r7   r7   r8   r    s    zAppIterRange.closeN)
rs   r2  r3  r4  r^   rP  rR  rS  __next__r  r7   r7   r7   r8   r1    s   	r1  c               @   s6   e Zd ZdZdddZdd Zdd Zd	d
 ZeZdS )r%  z
    An empty WSGI response.

    An iterator that immediately stops. Optionally provides a close
    method to close an underlying ``app_iter`` it replaces.
    Nc             C   s   |d k	rt |dr|j| _d S )Nr  )rP   r  )rS   rV   r7   r7   r8   r^     s    zEmptyResponse.__init__c             C   s   | S )Nr7   )rS   r7   r7   r8   rP    s    zEmptyResponse.__iter__c             C   s   dS )Nr   r7   )rS   r7   r7   r8   __len__  s    zEmptyResponse.__len__c             C   s
   t  d S )N)rQ  )rS   r7   r7   r8   rS    s    zEmptyResponse.next)N)	rs   r2  r3  r4  r^   rP  rU  rS  rT  r7   r7   r7   r8   r%    s   
r%  c             C   s2   |  dp0|  dr| dp0|  do0| dS )Nzapplication/xmlzapplication/z+xmlzimage/)rd   endswith)rW   r7   r7   r8   _is_xml  s
    



rW  c             C   s   |  dpt| S )Nztext/)rd   rW  )rW   r7   r7   r8   rE   	  s    
rE   c             C   s   | d d }|  dr$|| d 7 }n|| d d | d  7 }|dr`| d dkr`|d	d
 }n"|dr| d dkr|d	d }tr|  dd}|  dd}n$t|  ddd}t|  ddd}|t|7 }t|}d| kr||dd	 7 }n||7 }|S )zeLike ``wsgiref.url.request_uri``, except eliminates ``:80`` ports.

    Returns the full request URI.zwsgi.url_schemez://Z	HTTP_HOSTZSERVER_NAMEr.   ZSERVER_PORTz:80httpNz:443httpsZSCRIPT_NAMEr   Z	PATH_INFOrw   zlatin-1ra   )r   rV  r	   r
   r   )r   urlscript_nameZ	path_infoZ
qpath_infor7   r7   r8   r    s&    
r  c             C   s   t | dr|   d S )Nr  )rP   r  )rN  r7   r7   r8   rq   .  s    
rq   c             c   s   d}t dd@ }t dt jt j t jd}tV  x<| D ]4}|t|7 }t ||d@ }||}|r8|V  q8W |	 }|r|V  t
d||d@ V  d S )Nr   r0   l    	   z<2L)r  crc32compressobjDEFLATED	MAX_WBITSDEF_MEM_LEVEL_gzip_headerrM   compressrK  structpack)rV   sizecrcre  rH  r   r7   r7   r8   r  2  s    



r  c             C   sD   t | }t|dkr0|d d d |dd   }td||f d S )N2      z...iz>An item of the app_iter (%s) was text, causing a text body: %r)reprrM   r=   )rV   rT   Zapp_iter_reprr7   r7   r8   r   J  s    r   )r@  )rC  )Lrerf  r  base64r   r   r   hashlibr   Zwebob.byteranger   Zwebob.cachecontrolr   r   Zwebob.compatr	   r
   r   r   r   r   r   Zwebob.cookiesr   r   Zwebob.datetime_utilsr   r   r   Zwebob.descriptorsr   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   Zwebob.headersr$   Zwebob.requestr%   Z
webob.utilr&   r'   r(   Z
simplejsonr,   ImportError__all__compileIr   r   rd  objectrB   r)   r*  r   r   r1  r%  rW  rE   r  rq   r  r   r7   r7   r7   r8   <module>   sZ   $	D          F

*8