Your IP : 216.73.216.196


Current Path : /opt/alt/python37/lib/python3.7/site-packages/webtest/__pycache__/
Upload File :
Current File : //opt/alt/python37/lib/python3.7/site-packages/webtest/__pycache__/app.cpython-37.pyc

B

j��OB��@s(dZddlZddlZddlZddlZddlZddlZddlZddlm	Z	ddlm
Z
ddlmZddlmZddlm
Z
mZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZddlmZmZe�rHddl m!Z"nddl m"Z"ddgZ#Gdd�de$�Z%Gdd�de&�Z'Gdd �d e�Z(Gd!d�de�Z)Gd"d�de$�Z*e�+d#ej,�Z-d$d%�Z.Gd&d'�d'e$�Z/Gd(d)�d)e$�Z0Gd*d+�d+e/�Z1e1e/j2d,<Gd-d.�d.e/�Z3e3e/j2d/<Gd0d1�d1e1�Z4e4e/j2d2<Gd3d4�d4e/�Z5e5e/j2d5<Gd6d7�d7e/�Z6e6e/j2d8<Gd9d:�d:e/�Z7e7e/j2d;<Gd<d=�d=e6�Z8e8e/j2d><Gd?d@�d@e6�Z9e9e/j2dA<GdBdC�dCe/�Z:e:e/j2dD<e:e/j2dE<e:e/j2dF<GdGdH�dHe$�Z;dIdJ�Z<dVdKdL�Z=dWdNdO�Z>dPdQ�Z?dRdS�Z@dTdU�ZAdS)XzF
Routines for testing WSGI applications.

Most interesting is TestApp
�N)�urlparse)�print_stderr)�StringIO)�BytesIO)�SimpleCookie�CookieError)�cookie_quote)�	urlencode)�	splittype)�	splithost)�string_types)�binary_type)�	text_type)�	to_string)�to_bytes)�
join_bytes)�OrderedDict)�dumps)�loads)�PY3)�Request�Response)�lint3)�lint�TestApp�TestRequestc@seZdZdS)�	NoDefaultN)�__name__�
__module__�__qualname__�r r �</opt/alt/python37/lib/python3.7/site-packages/webtest/app.pyr/src@seZdZdd�ZdS)�AppErrorc	Gs�t|�}d}x�|D]z}t|t�rN|j}t|t�r�|jrD|�|j�}q�t|�}n4t|t�r�yt|�}Wntk
r�t|�}YnX||f7}qW||}t	�
||�dS)Nr )r�
isinstancer�bodyr
�charset�decode�repr�UnicodeDecodeError�	Exception�__init__)�self�message�argsZstr_args�argr$r r r!r*5s"




zAppError.__init__N)rrrr*r r r r!r"3sr"c@sveZdZdZdZdZdd�Zeedd�Zdd�Z	ee	d	d�Z
ed
d��Ze�
dejejB�Zd
d�Zdd�Zd8dd�Zd9dd�Zdd�Zd:dd�Ze�
ed��ZdZdd�Zeed��d�Zdd �Zeed!��d�Zd"d#�Zd$d%�Z d&d'�Z!d(d)�Z"d*d+�Z#d,d-�Z$ee$e$jd�Z$d.d/�Z%ee%e%jd�Z%d0d1�Z&ee&e&jd�Z&d2d3�Z'ee'e'jd�Z'd4d5�Z(ee(e(jd�Z(d6d7�Z)dS);�TestResponsez;
    Instances of this class are return by ``TestApp``
    NcCs|jdkr|��|jS)z�
        Returns a dictionary of :class:`~webtest.Form` objects.  Indexes are
        both in order (from zero) and by form id (if the form is given an id).
        N)�_forms_indexed�_parse_forms)r+r r r!�
forms__getSs
zTestResponse.forms__getz_
                     A list of :class:`~webtest.Form`s found on the page
                     )�doccCs*|j}|std��d|kr"td��|dS)Nz*You used response.form, but no forms exist�z5You used response.form, but more than one form existsr)�forms�	TypeError)r+r5r r r!�	form__getaszTestResponse.form__getz�
                    Returns a single :class:`~webtest.Form` instance; it is an
                    error if there are multiple forms on the page.
                    cCs,t|dd�r|jr|jStr&t|j�S|jS)N�_use_unicodeT)�getattrr%�unicode_bodyrrr$)r+r r r!�testbodyrs

zTestResponse.testbodyz<(/?)([:a-z0-9_\-]*)(.*?)>c
Cs�i}|_g}d}x�|j�|j�D]|}|�d�dk}|�d���}|dkrLq"|r�|sdtd|����|�|j||�	���d}q"|r�td|����|��}q"W|r�td|j|d���x6t
|�D]*\}}t||�}	|	||<|	jr�|	||	j<q�WdS)Nr4�/��formz</form> unexpected at %szNested form tags at %szDanging form: %r)
r0�_tag_re�finditerr;�group�lower�AssertionError�start�append�end�	enumerate�Form�id)
r+r5Z
form_texts�started�matchrF�tag�i�textr>r r r!r1|s.

zTestResponse._parse_formscKsT|jdkr|jdks"td|j��|jd}t|�\}}t|�\}}|jj|f|�S)z�
        If this request is a redirect, follow that redirect.  It
        is an error if this is not a redirect response.  Returns
        another response object.
        i,i�z/You can only follow redirect responses (not %s)�location)�
status_intrC�status�headersr
r�test_app�get)r+�kwrO�type�rest�host�pathr r r!�follow�s

zTestResponse.followFcCs8d}|jddd||||||d�	\}	}
}|j|d|d�S)a�
        Click the link as described.  Each of ``description``,
        ``linkid``, and ``url`` are *patterns*, meaning that they are
        either strings (regular expressions), compiled regular
        expressions (objects with a ``search`` method), or callables
        returning true or false.

        All the given patterns are ANDed together:

        * ``description`` is a pattern that matches the contents of the
          anchor (HTML and all -- everything between ``<a...>`` and
          ``</a>``)

        * ``linkid`` is a pattern that matches the ``id`` attribute of
          the anchor.  It will receive the empty string if no id is
          given.

        * ``href`` is a pattern that matches the ``href`` of the anchor;
          the literal content of that attribute, not the fully qualified
          attribute.

        * ``anchor`` is a pattern that matches the entire anchor, with
          its contents.

        If more than one link matches, then the ``index`` link is
        followed.  If ``index`` is not given and more than one link
        matches, or if no link matches, then ``IndexError`` will be
        raised.

        If you give ``verbose`` then messages will be printed about
        each link, and why it does or doesn't match.  If you use
        ``app.click(verbose=True)`` you'll see a list of all the
        links.

        You can use multiple criteria to essentially assert multiple
        aspects about the link, e.g., where the link's destination is.
        T�a�hrefN)	rL�	href_attr�href_extract�contentrI�href_pattern�html_pattern�index�verbose�uri)�
extra_environ)�
_find_element�goto)r+�descriptionZlinkidr\�anchorrbrcre�__tracebackhide__�
found_html�
found_desc�found_attrsr r r!�click�s(zTestResponse.clickcCs:d}|jddt�d�||||||d�	\}}	}
|�|
d�S)z�
        Like ``.click()``, except looks for link-like buttons.
        This kind of button should look like
        ``<button onclick="...location.href='url'...">``.
        T�buttonZonclickzlocation\.href='(.*?)')	rLr]r^r_rIr`rarbrcrd)rf�re�compilerg)r+rhZbuttonidr\rorbrcrjrkrlrmr r r!�clickbutton�szTestResponse.clickbuttonc
 s�t|�}
t|�}t|�}t|�}
|j}t�d||ftjtj�}t�dtjtjB�}g}x(|�|�D]}|�|��|�	�f�qfW�fdd�}g}d}�x�|�|�D�]�}d}x.|D]&\}}|��|kr�|�	�|kr�d}Pq�W|r�q�|�
d�}|�
d�}|�
d	�}t|�}��r|d
|�|�|��s8|d|�q�||}|�rj|�
|�}|�s`|d�q�|�
d�}||d
<|�d��r�|d�q�|�d��r�|d�q�|d7}|
�r�|
|��s�|d�q�|�r�||�dd���s�|d�q�|�r�||��s�|d�q�|
�r|
|��s|d�q�|d�|�|||f�q�W|�sDtd|��|dk�r�t|�dk�rxtdd�dd�|D����|d}n:y||}Wn,tk
�r�tdt|�||f��YnX|S)Nz<%s\s+(.*?)>(.*?)</%s>z<script.*?>.*?</script>cs�rt|�dS)N)�print)�s)rcr r!�printlog�sz,TestResponse._find_element.<locals>.printlogrFTr4r=zElement: %rz  Skipped: no %s attributez(  Skipped: doesn't match extract patternrd�#z&  Skipped: only internal fragment hrefzjavascript:z$  Skipped: cannot follow javascript:z$  Skipped: doesn't match descriptionrI�z  Skipped: doesn't match idz  Skipped: doesn't match hrefz  Skipped: doesn't match htmlz
  Acceptedz-No matching elements found (from %s possible)zMultiple links match: %sz, cSsg|]\}}}t|��qSr )r')�.0Zanc�d�attrr r r!�
<listcomp>:sz.TestResponse._find_element.<locals>.<listcomp>z6Only %s (out of %s) links match; index %s out of range)�
_make_patternr;rprq�I�Sr@rErDrFrA�_parse_attrsrT�search�
startswith�
IndexError�len�join) r+rLr]r^r_rIr`rarbrcZcontent_patZid_patZhref_patZhtml_patr$r?Z
_script_reZ	bad_spansrKruZfound_linksZtotal_linksZ	found_badZ	bad_startZbad_endZel_htmlZel_attrZ
el_content�attrsZel_href�mZ
found_linkr )rcr!rf�s�






zTestResponse._find_elementrTc	st�|�\}}}}}d}}}t�|||||f�}t��jj|�}|��}|dks`td|��ts�t	�dd�r�fdd���|�}d|kr��fd	d
�|dD�|d<d|krȇfdd
�|dD�|d<d
|kr�|d
�|d
<|dkr�j
j}n�j
j}||f|�S)a
        Go to the (potentially relative) link ``href``, using the
        given method (``'get'`` or ``'post'``) and any extra arguments
        you want to pass to the ``app.get()`` or ``app.post()``
        methods.

        All hostnames and schemes will be ignored.
        rw)rT�postz9Only "get" or "post" are allowed for method (you gave %r)r8Fcst|t�r|��j�S|S)N)r#r�encoder%)rt)r+r r!�to_strZs
z!TestResponse.goto.<locals>.to_str�paramscsg|]}tt�|���qSr )�tuple�map)rx�p)r�r r!r{bsz%TestResponse.goto.<locals>.<listcomp>�upload_filescsg|]}t�|��qSr )r�)rx�f)r�r r!r{fs�content_typerT)
r�urlsplit�
urlunsplit�urljoin�request�urlrBrCrr9rSrTr�)	r+r\�methodr-�schemerXrY�query�fragmentr )r+r�r!rgEs.	



zTestResponse.gotoz
[ \n\r\t]+cCs&|jdkr |j�td�|j�|_|jS)N� )�_normal_body�_normal_body_regex�subrr$)r+r r r!�normal_body__getvs
zTestResponse.normal_body__getz]
                           Return the whitespace-normalized body
                           cCs|jstd��|j�|j�S)NzDYou cannot access Response.unicode_normal_body unless charset is set)r%�AttributeError�normal_bodyr&)r+r r r!�unicode_normal_body__get�sz%TestResponse.unicode_normal_body__getzC
        Return the whitespace-normalized body, as unicode
        cCsrt|t�s&t|d�r|��}nt|�}t|t�r>|js>t|�}t|t�rV|j}|j	}n|j
}|j}||kpp||kS)z�
        A response 'contains' a string if it is present in the body
        of the response.  Whitespace is normalized when searching
        for a string.
        �__unicode__)r#r�hasattrr��strrr%rr:�unicode_normal_bodyr$r�)r+rtr$r�r r r!�__contains__�s



zTestResponse.__contains__cOs�d|kr(|d}|d=t|t�r,|g}ng}|r8td��x8|D]0}||kr>td|�tt|��td|��q>Wx8|D]0}||krxtd|�tt|��td|��qxWdS)z�
        Assert that the response contains all of the strings passed
        in as arguments.

        Equivalent to::

            assert string in res
        �noz)The only keyword argument allowed is 'no'zActual response (no %r):zBody does not contain string %rzActual response (has %r)zBody contains bad string %rN)r#rr6rr�r�)r+�stringsrUr�rtZno_sr r r!�mustcontain�s*	


zTestResponse.mustcontaincsZd�dd��j��D��}�fdd��jD�}|��dt�j�d�dd�|D��|fS)N�
cSsg|]}|��r|�qSr )�strip)rx�lr r r!r{�sz(TestResponse.__str__.<locals>.<listcomp>cs*g|]"\}}|��dkr��|�|f�qS)zcontent-length)rB�_normalize_header_name)rx�n�v)r+r r!r{�szResponse: %s
%s
%scSsg|]\}}d||f�qS)z%s: %sr )rxr�r�r r r!r{�s)r�r;�
splitlinesZ
headerlist�sortrrQ)r+Zsimple_bodyrRr )r+r!�__str__�s

zTestResponse.__str__cCs|�dd����dd�}|S)N�-r�)�replace�title)r+�namer r r!r��sz#TestResponse._normalize_header_namecCs�|jrd|j}nd}|jrjt|j�}t|�dkr`|dd�d|dd�}|dt|j�7}d|}nd	}|jr�d
|j}nd}dt|j�|||dS)
Nz %srw��
z...���z/%sz body=%sz no bodyz
 location: %s�<�>)r�r$r'r�rOrrQ)r+Zct�brr$rOr r r!�__repr__�s

zTestResponse.__repr__cCsTd|jkrtd|j��yddlm}Wntk
rDtd��YnX||j�}|S)z�
        Returns the response as a `BeautifulSoup
        <http://www.crummy.com/software/BeautifulSoup/documentation.html>`_
        object.

        Only works with HTML responses; other content-types raise
        AttributeError.
        �htmlz,Not an HTML response body (content-type: %s)r)�
BeautifulSoupz:You must have BeautifulSoup installed to use response.html)r�r�r��ImportErrorr;)r+r�Zsoupr r r!r��s	


zTestResponse.htmlcCs�d|jkrtd|j��yddlm}Wndtk
r�yddl}WnBtk
r�yddlm}Wntk
r�td��YnXYnXYnX|�|j�S)z�
        Returns the response as an `ElementTree
        <http://python.org/doc/current/lib/module-xml.etree.ElementTree.html>`_
        object.

        Only works with XML responses; other content-types raise
        AttributeError
        �xmlz+Not an XML response body (content-type: %s)r)�ElementTreeNzKYou must have ElementTree installed (or use Python 2.5) to use response.xml)r�r�Z	xml.etreer�r�Zelementtree�XMLr$)r+r�r r r!r��s 	

zTestResponse.xmlcCs�d|jkr"d|jkr"td|j��yddlm}Wntk
rNtd��YnXyddlm}Wntk
rz|j}YnX|jdkr�||j|j	j
d	�S|j|j|j	j
d	�Sd
S)a{
        Returns the response as an `lxml object
        <http://codespeak.net/lxml/>`_.  You must have lxml installed
        to use this.

        If this is an HTML response and you have lxml 2.x installed,
        then an ``lxml.html.HTML`` object will be returned; if you
        have an earlier version of lxml then a ``lxml.HTML`` object
        will be returned.
        r�r�z3Not an XML or HTML response body (content-type: %s)r)�etreez1You must have lxml installed to use response.lxml)�
fromstringz	text/html)Zbase_urlN)r�r��lxmlr�r�Z	lxml.htmlr�ZHTMLr;r�r�r�)r+r�r�r r r!r�s"



zTestResponse.lxmlcCs2|jdkrtd|j��tdkr(td��t|j�S)a
        Return the response as a JSON response.  You must have `simplejson
        <http://goo.gl/B9g6s>`_ installed to use this, or be using a Python
        version with the json module.

        The content type must be application/json to use this.
        zapplication/jsonz+Not a JSON response body (content-type: %s)Nz7You must have simplejson installed to use response.json)r�r�rr�r;)r+r r r!�json>s

zTestResponse.jsoncCs^d|jkr"d|jkr"td|j��yddlm}Wntk
rNtd��YnX||j�}|S)z�
        Returns the response as a `PyQuery <http://pyquery.org/>`_ object.

        Only works with HTML and XML responses; other content-types raise
        AttributeError.
        r�r�z3Not an HTML or XML response body (content-type: %s)r)�PyQueryz7You must have PyQuery installed to use response.pyquery)r�r��pyqueryr�r�r;)r+r�ryr r r!r�Qs

zTestResponse.pyquerycCszddl}ddl}|jddd�}|j}|��t|d�}|�t|j��|��|ddkrdd|}nd	|}|�	|�dS)
z{
        Show this response in a browser window (for debugging purposes,
        when it's hard to read the HTML).
        rNzwebtest-pagez.html)�prefix�suffix�wr<zfile:///zfile://)
�
webbrowser�tempfile�NamedTemporaryFiler��close�open�writerr$Zopen_new)r+r�r�r�r�r�r r r!�showbrowserfs

zTestResponse.showbrowser)NNNNNFN)NNNNNF)rT)*rrr�__doc__r�r0r2�propertyr5r7r>r;rprqr~r}r?r1rZrnrrrfrgrr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r r r r!r/JsZ	
1
[
- r/c@seZdZdZeZdS)rTN)rrr�disabledr/Z
ResponseClassr r r r!r|sc@s�eZdZdZdZeZd.dd�Zdd�Zd/dd	�Z	d
d�Z
d0d
d�Zd1dd�Zd2dd�Z
eddddfdd�Zd3dd�Zeddddfdd�Zd4dd�Zeddddfdd�Zd5dd�Zd6d d!�Zd"d#�Zd$d%�Zd7d&d'�Zd(d)�Zd*d+�Zd,d-�ZdS)8ra	
    Wraps a WSGI application in a more convenient interface for
    testing.

    ``app`` may be an application, or a Paste Deploy app
    URI, like ``'config:filename.ini#test'``.

    ``extra_environ`` is a dictionary of values that should go
    into the environment for each request.  These can provide a
    communication channel with the application.

    ``relative_to`` is a directory, and filenames used for file
    uploads are calculated relative to this.  Also ``config:``
    URIs that aren't absolute.
    TNcCsRt|t�r"ddlm}|||d�}||_||_|dkr:i}||_||_|��dS)Nr)�loadapp)�relative_to)	r#rZpaste.deployr��appr�re�use_unicode�reset)r+r�rer�r�r�r r r!r*�s
zTestApp.__init__cCs
i|_dS)zc
        Resets the state of the application; currently just clears
        saved cookies.
        N)�cookies)r+r r r!r��sz
TestApp.resetcCs$|j��}d|d<|r |�|�|S)NTzpaste.throw_errors)re�copy�update)r+re�environr r r!�
_make_environ�s


zTestApp._make_environcCs(t�|�\}}}}}t�||||df�S)Nrw)rr�r�)r+r�r��netlocrYr�r�r r r!�_remove_fragment�szTestApp._remove_fragmentFc
Cs�|�|�}d}t|�}|�|�}|r\t|t�s:t|dd�}d|krL|d7}n|d7}||7}d|krz|�dd�\}|d<nd|d<|j�||�}	|r�|	j	�
|�|j|	||d�S)	a�
        Get the given url (well, actually a path like
        ``'/page.html'``).

        ``params``:
            A query string, or a dictionary that will be encoded
            into a query string.  You may also include a query
            string on the ``url``.

        ``headers``:
            A dictionary of extra headers to send.

        ``extra_environ``:
            A dictionary of environmental variables that should
            be added to the request.

        ``status``:
            The integer status code you expect (if not 200 or 3xx).
            If you expect a 404 response, for instance, you must give
            ``status=404`` or it will be an error.  You can also give
            a wildcard, like ``'3*'`` or ``'*'``.

        ``expect_errors``:
            If this is not true, then if anything is written to
            ``wsgi.errors`` it will be an error.  If it is true, then
            non-200/3xx responses are also okay.

        Returns a :class:`webtest.TestResponse` object.
        T)�doseq�?�&r4�QUERY_STRINGrw)rQ�
expect_errors)r�r�r�r#rr	�split�RequestClass�blankrRr��
do_request)
r+r�r�rRrerQr�r�rj�reqr r r!rT�s&



zTestApp.getrwc
Cs�|�|�}
t||	�}|s*|	rVt|	��d�rVtj|dd�}|�||pDd�\}	}|	|
d<n|rf|
�dd�d|kr�|�dd�\}|
d	<nd
|
d	<|	dk	r�|	|
d<t	t
|��|
d<||
d
<tt|��|
d<|�
|�}|j�||
�}|r�|j�|�|j|||d�S)z'
        Do a generic request.
        �	multipartT)�keep_blank_valuesr ZCONTENT_TYPEz!application/x-www-form-urlencodedr�r4r�rwNZCONTENT_LENGTHZREQUEST_METHODz
wsgi.input)rQr�)r��
encode_paramsrr��cgi�	parse_qsl�encode_multipart�
setdefaultr�r�r�rrr�r�r�rRr�r�)r+r�r�r�rRrerQr�r�r�r�r�r r r!�_gen_request�s2



zTestApp._gen_requestc		Cs|jd||||||||d�	S)a�
        Do a POST request.  Very like the ``.get()`` method.
        ``params`` are put in the body of the request.

        ``upload_files`` is for file uploads.  It should be a list of
        ``[(fieldname, filename, file_content)]``.  You can also use
        just ``[(fieldname, filename)]`` and the file content will be
        read from disk.

        Returns a ``webob.Response`` object.
        �POST)r�rRrerQr�r�r�)r�)	r+r�r�rRrerQr�r�r�r r r!r�s
zTestApp.postcCs0d}|tk	rt|�}|jd|||||d||d�	S)z�
        Do a POST request.  Very like the ``.get()`` method.
        ``params`` are dumps to json and put in the body of the request.
        Content-Type is set to ``application/json``.

        Returns a ``webob.Response`` object.
        zapplication/jsonr�N)r�rRrerQr�r�r�)rrr�)r+r�r�rRrerQr�r�r r r!�	post_json%s	zTestApp.post_jsonc		Cs|jd||||||||d�	S)a}
        Do a PUT request.  Very like the ``.post()`` method.
        ``params`` are put in the body of the request, if params is a
        tuple, dictionary, list, or iterator it will be urlencoded and
        placed in the body as with a POST, if it is string it will not
        be encoded, but placed in the body directly.

        Returns a ``webob.Response`` object.
        �PUT)r�rRrerQr�r�r�)r�)	r+r�r�rRrerQr�r�r�r r r!�put7s
zTestApp.putcCs0d}|tk	rt|�}|jd|||||d||d�	S)z�
        Do a PUT request.  Very like the ``.post()`` method.
        ``params`` are dumps to json and put in the body of the request.
        Content-Type is set to ``application/json``.

        Returns a ``webob.Response`` object.
        zapplication/jsonr�N)r�rRrerQr�r�r�)rrr�)r+r�r�rRrerQr�r�r r r!�put_jsonIs	zTestApp.put_jsoncCs.|rt�dtj�|jd|||||d||d�	S)zv
        Do a DELETE request.  Very like the ``.get()`` method.

        Returns a ``webob.Response`` object.
        zXYou are not supposed to send a body in a DELETE request. Most web servers will ignore it�DELETEN)r�rRrerQr�r�r�)�warnings�warnr�WSGIWarningr�)r+r�r�rRrerQr�r�r r r!�delete[szTestApp.deletecCsB|rt�dtj�d}|tk	r&t|�}|jd|||||d||d�	S)z�
        Do a DELETE request.  Very like the ``.get()`` method.
        Content-Type is set to ``application/json``.

        Returns a ``webob.Response`` object.
        zXYou are not supposed to send a body in a DELETE request. Most web servers will ignore itzapplication/jsonr�N)r�rRrerQr�r�r�)r�r�rr�rrr�)r+r�r�rRrerQr�r�r r r!�delete_jsonlszTestApp.delete_jsonc	Cs|jd||||d|d�S)zw
        Do a OPTIONS request.  Very like the ``.get()`` method.

        Returns a ``webob.Response`` object.
        ZOPTIONSN)rRrerQr�r�)r�)r+r�rRrerQr�r r r!�options�s
zTestApp.optionsc	Cs|jd||||d|d�S)zt
        Do a HEAD request.  Very like the ``.get()`` method.

        Returns a ``webob.Response`` object.
        ZHEADN)rRrerQr�r�)r�)r+r�rRrerQr�r r r!�head�s
zTestApp.headcCs�dt��}g}x@|D]8\}}|�d|�|�d|�|�d�|�|�qWxp|D]h}|�|�\}}}|�d|�|�d||f�t�|�d}	|�d|	p�d�|�d�|�|�qXW|�d|d�|�d�td	|�}
d
|}||
fS)z�
        Encodes a set of parameters (typically a name/value list) and
        a set of files (a list of (name, filename, file_body)) into a
        typical POST body, returning the (content_type, body).
        z----------a_BoUnDaRy%s$z--z)Content-Disposition: form-data; name="%s"rwz8Content-Disposition: form-data; name="%s"; filename="%s"rzContent-Type: %szapplication/octet-streamz
z multipart/form-data; boundary=%s)�randomrE�_get_file_info�	mimetypesZ
guess_typer)r+r��files�boundary�lines�key�value�	file_info�filenameZfcontentr$r�r r r!r��s.




zTestApp.encode_multipartcCs�t|�dkrl|d}|jr*tj�|j|�}t|d�}|��}trVt|t	�rV|�
|j�}|��|d||fSt|�dkr�|d}t|t
�s�tdt
t|�f��|Stdt|�dd���dS)	Nr=r4�rbr�zFile content must be %s not %szuupload_files need to be a list of tuples of (fieldname, filename, filecontent) or (fieldname, filename); you gave: %r�d)r�r��osrYr�r��readrr#rr��encodingr�r
�
ValueErrorrVr')r+r
rr�r_r r r!r�s&

zTestApp._get_file_infocKs�t|t�r|jj|f|�}n@|��}x |��D]\}}t|||�q.W|jdkr\t|j	�|_d|j
d<x$|j��D]\}}|j
�||�qrW|j
|||d�S)a
        Creates and executes a request.  You may either pass in an
        instantiated :class:`TestRequest` object, or you may pass in a
        URL and keyword arguments to be passed to
        :meth:`TestRequest.blank`.

        You can use this to run a request without the intermediary
        functioning of :meth:`TestApp.get` etc.  For instance, to
        test a WebDAV method::

            resp = app.request('/new-col', method='MKCOL')

        Note that the request won't have a body unless you specify it,
        like::

            resp = app.request('/test.txt', method='PUT', body='test')

        You can use ``POST={args}`` to set the request body to the
        serialized arguments, and simultaneously set the request
        method to ``POST``
        ���Tzpaste.throw_errors)rQr�)r#rr�r�r��items�setattrZcontent_lengthr�r$r�rer�r�)r+Z
url_or_reqrQr�Z
req_paramsr�r�r	r r r!r��s


zTestApp.requestc	Cs�d}t�}||jd<|j�dd�}|rF|j�|�rF|jt|�d�|_|jrpd�dd�|j��D��}||jd<d|jd	<i|jd
<t	�
|j�}|j|dd�}	|j
|	_||	_||	_||	_y
|	jWntk
r�YnX|��|	_x>|jd
��D],\}
}t|	|
��rtd|
��t|	|
|�q�W|�s>|�||	�|�|	�i|	_xx|	j�d
�D]h}yt|�}
Wn$tk
�r�td|f��YnXx.|
��D]"\}}|j|j|<|j|	j|<�q�W�qRW|	S)a�
        Executes the given request (``req``), with the expected
        ``status``.  Generally ``.get()`` and ``.post()`` are used
        instead.

        To use this::

            resp = app.do_request(webtest.TestRequest.blank(
                'url', ...args...))

        Note you can pass any keyword arguments to
        ``TestRequest.blank()``, which will be set on the request.
        These can be arguments like ``content_type``, ``accept``, etc.
        Tzwsgi.errorsZSCRIPT_NAMErwNcSs g|]\}}d|t|�f�qS)z%s=%s; )r)rxr�r	r r r!r{sz&TestApp.do_request.<locals>.<listcomp>ZHTTP_COOKIEz
paste.testingzpaste.testing_variables)Zcatch_exc_infozopaste.testing_variables contains the variable %r, but the response object already has an attribute by that namez
set-cookiez Could not parse cookie header %r) rr�rTZ	path_infor�r�r�r�rrZ
middlewarer�Zget_responser�r8r�rSr$r6�getvalue�errorsr�rr�
_check_status�
_check_errorsZcookies_setrRZgetallrrr	)r+r�rQr�rjr�script_nameZ
cookie_headerr��resr�r	�header�crZmorselr r r!r��sX






zTestApp.do_requestcCs�d}|dkrdSt|j�}t|t�rFd|krFt�t�|�|tj�rFdSt|t	t
f�r�|j|kr~td|d�
tt|��|jj|��dS|dkr�|jdkr�|jdkr�dStd||jj|��||jkr�td||��dS)	NT�*z*Bad response: %s (not one of %s for %s)
%sz, ��i�z7Bad response: %s (not 200 OK or 3xx redirect for %s)
%szBad response: %s (not %s))rrQr#rrprK�fnmatch�	translater}�listr�rPr"r�r�r�r�r�)r+rQrrjZ
res_statusr r r!r4s2



zTestApp._check_statuscCs|j}|rtd|��dS)Nz!Application had errors logged:
%s)rr")r+rrr r r!rOszTestApp._check_errors)NNT)N)NNNNF)rwNNNNFN)rwNNNNFN)rwNNNNFN)rwNNNFN)NNNF)NNNF)NF)rrrr�r�rr�r*r�r�r�rTr�r�rr�r�r�r�r�rrr�rr�r�rrr r r r!r�sJ


5
 





$?zW([^= \n\r\t]+)[ \n\r\t]*(?:=[ \n\r\t]*(?:"([^"]*)"|\'([^\']*)\'|([^"\'][^ \n\r\t>]*)))?cCsVi}xLt�|�D]>}|�d���}|�d�p4|�d�}t|p>d�}||t|�<qW|S)Nr4r=r
rw)�_attr_rer@rArB�html_unquoter�)rNr�rK�	attr_nameZ	attr_bodyr r r!r`src@sLeZdZdZiZdZddd�Zdd�Zdd	�Zd
d�Z	e
e	e�Zdd
�ZdS)�Fieldz
    Field object.
    TNcKs.||_||_||_||_||_||_||_dS)N)r>rLr��pos�_valuerIr�)r+r>rLr�r'r	rIr�r r r!r*xszField.__init__cCs$|jstd|j|jf��||_dS)Nz-You cannot set the value of the <%s> field %r)�settabler�rLr�r()r+r	r r r!�
value__set�s
zField.value__setcCs
||_dS)z^
        Like setting a value, except forces it even for, say, hidden
        fields.
        N)r()r+r	r r r!�force_value�szField.force_valuecCs|jS)N)r()r+r r r!�
value__get�szField.value__getcCs.d|jj|jf}|jr&|d|j7}|dS)Nz
<%s name="%s"z id="%s"r�)�	__class__rr�rI)r+r	r r r!r��szField.__repr__)NN)
rrrr��classesr)r*r*r+r,r�r	r�r r r r!r&ms
	
r&c@seZdZdS)�NoValueN)rrrr r r r!r/�sr/csBeZdZdZ�fdd�Zdd�Zdd�Zdd	�Zeee�Z	�Z
S)
�Selectz)
    Field representing ``<select>``
    cs(tt|�j||�g|_d|_t|_dS)N)�superr0r*r�
selectedIndexr/�
_forced_value)r+r-r�)r-r r!r*�szSelect.__init__cCs
||_dS)N)r3)r+r	r r r!r+�szSelect.force_valuecCsf|jtk	rt|_xPt|j�D] \}\}}|t|�kr||_PqWtd|d�dd�|jD��f��dS)NzOption %r not found (from %s)z, cSsg|]\}}t|��qSr )r')rx�orr r r!r{�sz%Select.value__set.<locals>.<listcomp>)r3r/rGr�
_stringifyr2rr�)r+r	rM�option�checkedr r r!r*�s
zSelect.value__setcCsb|jtk	r|jS|jdk	r*|j|jdSx2|jD]\}}|r2|Sq2W|jrZ|jddSdSdS)Nr)r3r/r2r)r+r6r7r r r!r,�s

zSelect.value__get)rrrr�r*r+r*r,r�r	�
__classcell__r r )r-r!r0�s
r0�selectcsBeZdZdZ�fdd�Zdd�Zdd�Zdd	�Zeee�Z	�Z
S)
�MultipleSelectz=
    Field representing ``<select multiple="multiple">``
    cs(tt|�j||�g|_g|_g|_dS)N)r1r:r*r�selectedIndices�_forced_values)r+r-r�)r-r r!r*�szMultipleSelect.__init__cCs||_g|_dS)N)r<r;)r+�valuesr r r!r+�szMultipleSelect.force_valuecCs~dd�|D�}g|_x8t|j�D]*\}\}}||kr |j�|�|�|�q W|rztdd�|�d�dd�|jD��f��dS)NcSsg|]}t|��qSr )r5)rxr	r r r!r{�sz-MultipleSelect.value__set.<locals>.<listcomp>z Option(s) %r not found (from %s)z, cSsg|]\}}t|��qSr )r')rxr4rr r r!r{�s)ZselectedIndiciesrGrr;rE�removerr�)r+r=Z
str_valuesrMr6r7r r r!r*�szMultipleSelect.value__setcsng}�jr �fdd��jD�}n,�jsLg}x �jD]\}}|r2|�|�q2W�jr\|�j7}�jrj|sjd}|S)Ncsg|]}�j|d�qS)r)r)rxrM)r+r r!r{�sz-MultipleSelect.value__get.<locals>.<listcomp>)r;r<rrE)r+Zselected_valuesr6r7r )r+r!r,�s


zMultipleSelect.value__get)rrrr�r*r+r*r,r�r	r8r r )r-r!r:�sr:�multiple_selectc@s$eZdZdZdd�Zeeej�ZdS)�Radioz5
    Field representing ``<input type="radio">``
    cCs>|jdk	r|j|jdSx|jD]\}}|r"|Sq"WdSdS)Nr)r2r)r+r6r7r r r!r,s
zRadio.value__getN)	rrrr�r,r�r0r*r	r r r r!r@s
r@�radiocs:eZdZdZ�fdd�Zdd�Zdd�Zeee�Z�Z	S)�Checkboxz8
    Field representing ``<input type="checkbox">``
    cs tt|�j||�d|k|_dS)Nr7)r1rBr*r7)r+r-r�)r-r r!r*!szCheckbox.__init__cCs||_dS)N)r7)r+r	r r r!r*%szCheckbox.value__setcCs$|jr|jdkrdS|jSndSdS)N�on)r7r()r+r r r!r,(s

zCheckbox.value__get)
rrrr�r*r*r,r�r	r8r r )r-r!rBs
	rBZcheckboxc@s$eZdZdZdd�Zeeej�ZdS)�Textz4
    Field representing ``<input type="text">``
    cCs|jdkrdS|jSdS)Nrw)r()r+r r r!r,;s
zText.value__getN)	rrrr�r,r�r&r*r	r r r r!rD6srDrNc@s$eZdZdZdd�Zeeej�ZdS)�Filez4
    Field representing ``<input type="file">``
    cCs|jdkrdS|jSdS)Nrw)r()r+r r r!r,Ls
zFile.value__getN)	rrrr�r,r�r&r*r	r r r r!rEFsrE�filec@seZdZdZdS)�Textareaz+
    Field representing ``<textarea>``
    N)rrrr�r r r r!rGWsrG�textareac@seZdZdZdS)�Hiddenz6
    Field representing ``<input type="hidden">``
    N)rrrr�r r r r!rI_srIZhiddenc@s,eZdZdZdZdd�Zee�Zdd�ZdS)�SubmitzG
    Field representing ``<input type="submit">`` and ``<button>``
    FcCsdS)Nr )r+r r r!r,nszSubmit.value__getcCs|jS)N)r()r+r r r!�value_if_submittedsszSubmit.value_if_submittedN)	rrrr�r)r,r�r	rKr r r r!rJgs
rJ�submitroZimagec@s�eZdZdZe�dej�Ze�dej�Ze	Z
dd�Zdd�Zdd	�Z
d
d�Zdd
�Zdd�Zddd�Zdefdd�Zd dd�Zd!dd�Zdd�Zd"dd�Zdd�ZdS)#rHa
    This object represents a form that has been found in a page.
    This has a couple useful attributes:

    ``text``:
        the full HTML of the form.

    ``action``:
        the relative URI of the action.

    ``method``:
        the method (e.g., ``'GET'``).

    ``id``:
        the id, or None if not given.

    ``fields``:
        a dictionary of fields, each value is a list of fields by
        that name.  ``<input type="radio">`` and ``<select>`` are
        both represented as single fields with multiple options.
    z<(/?)([a-z0-9_\-]*)([^>]*?)>z<<label\s+(?:[^>]*)for=(?:"|')([a-z0-9_\-]+)(?:"|')(?:[^>]*)>cCs ||_||_|��|��dS)N)�responserN�
_parse_fields�
_parse_action)r+rMrNr r r!r*�sz
Form.__init__cCs�d}d}t�}�xv|j�|j�D�]b}|�d�dk}|�d���}|dkrLq |dkrt|rt|sntd|�d���d}q |dkr�|r�|s�td	|����t|j|d|����|d_	d}q |r�q t
|�d
��}d|kr�|�d�}nd}|dk�r|j�
|�d
�d|kf�q |dk�r�|�d�dk�r�|�|�}	|	�sh|jjd||||��f|�}	|�|g��
|	�n |	d}	t|	|jjd��s�t�|	j�
|�d
�d|kf�q |}
|dk�r�|�dd���}
|
dk�r�|�d��r�|jj�d|j�}n|jj�|
|j�}|||||��f|�}	|dk�rH|�r:td||�d�f��|	|��f}n*|dk�rr|�rntd||�d�f��|	}|�|g��
|	�q W||_dS)Nr4r<r=)�inputr9r6rHror9z%r without starting selectrrHz$</textarea> with no <textarea> at %sr
r�r6r	�selectedrPrVrAr7rNZmultipler?zNested textareas: %r and %rzNested selects: %r and %r)rr?r@rNrArBrCrDr$r	r�poprrErT�
FieldClassr.r�r#rF�fields)r+Z	in_selectZin_textarearTrKrFrLr�r��fieldZtag_typerSr r r!rN�s|








zForm._parse_fieldscCs�d|_x�|j�|j�D]t}|�d�dk}|�d���}|dkr@q|rFPt|�d��}|�dd�|_|�dd	�|_|�d
�|_	|�dd�|_
qWd
s�td��|jdk	s�td��dS)Nr4r<r=r>r
�actionrwr��GETrI�enctypez!application/x-www-form-urlencodedrzNo </form> tag foundzNo <form> tag found)rVr?r@rNrArBrrTr�rIrXrC)r+rKrFrLr�r r r!rO�s"zForm._parse_actionc	Csl|j�|�}|dk	s6td|d�tt|j����f��t|�dks^td|d�tt|��f��||d_dS)a�
        Set the value of the named field.  If there is 0 or multiple
        fields by that name, it is an error.

        Setting the value of a ``<select>`` selects the given option
        (and confirms it is an option).  Setting radio fields does the
        same.  Checkboxes get boolean values.  You cannot set hidden
        fields or buttons.

        Use ``.set()`` if there is any ambiguity and you must provide
        an index.
        Nz*No field by the name %r found (fields: %s)z, r4zMultiple fields match %r: %sr)	rTrTrCr�r�r'�keysr�r	)r+r�r	rTr r r!�__setitem__�s

zForm.__setitem__cCsP|j�|�}|dk	s td|��t|�dksHtd|d�tt|��f��|dS)zE
        Get the named field object (ambiguity is an error).
        NzNo field by the name %r foundr4zMultiple fields match %r: %sz, r)rTrTrCr�r�r�r')r+r�rTr r r!�__getitem__s

zForm.__getitem__cCsp|j�|j�}x\|j��D]N\}}xD|D]<}t|ttf�s(|jsNt	d|��q(|j|kr(t	d|��q(WqWdS)zsCheck that the html is valid:

        - each field must have an id
        - each field must have a label
        z%r as no id attributez%r as no associated labelN)
�	_label_re�findallrNrTrr#rJrIrIr�)r+�labelsr�rTrUr r r!rs

z	Form.lintNcCsD|dkr|||<n.|j�|�}|dk	s2td|��||}||_dS)zF
        Set the given name, using ``index`` to disambiguate.
        NzNo fields found matching %r)rTrTrCr	)r+r�r	rbrTrUr r r!�set0s


zForm.setcCs`|j�|�}|dkr |tk	r |S|dkr0||S|j�|�}|dk	sPtd|��||}|SdS)zb
        Get the named/indexed field object, or ``default`` if no field
        is found.
        NzNo fields found matching %r)rTrTrrC)r+r�rb�defaultrTrUr r r!rT=s

zForm.getcCs&|j||d�}t|t�st�||_dS)z]
        Like ``.set()``, except also confirms the target is a
        ``<select>``.
        )rbN)rTr#r0rCr	)r+r�r	rbrUr r r!r9NszForm.selectcKsX|j||d�}|��}|r"||d<|jdkr:|�d|j�|jj|jf|j|d�|��S)a
        Submits the form.  If ``name`` is given, then also select that
        button (using ``index`` to disambiguate)``.

        Any extra keyword arguments are passed to the ``.get()`` or
        ``.post()`` method.

        Returns a :class:`webtest.TestResponse` object.
        )rbr�rWr�)r�r�)�
submit_fields�
upload_fieldsr�r�rXrMrgrV)r+r�rbr-rT�uploadsr r r!rLWs

zForm.submitcCsTg}xJ|j��D]<\}}x2|D]*}t|t�r|jr|�|gt|j��qWqW|S)z�
        Return a list of file field tuples of the form:
            (field name, file name)
        or
            (field name, file name, file contents).
        )rTrr#rEr	rEr")r+rcr�rTrUr r r!rbjs
zForm.upload_fieldscCs�g}|dk	r.|j||d�}|�|j|��f�x�|j��D]r\}}|dkrLq:x^|D]V}|j}|dkrfqRt|t�rrqRt|t	�r�x*|D]}|�||f�q�WqR|�||f�qRWq:W|S)zf
        Return a list of ``[(name, value), ...]`` for the current
        state of the form.
        N)rb)
rTrEr�rKrTrr	r#rEr")r+r�rbrLrUrTr	�itemr r r!raxs$



zForm.submit_fieldscCs$d}|jr|dt|j�7}|dS)Nz<Formz id=%rz />)rIr�)r+r	r r r!r��sz
Form.__repr__)N)N)NN)NN)rrrr�rprqr}r?r\r&rSr*rNrOrZr[rr_rrTr9rLrbrar�r r r r!rH}s&D


	

rHcCst|t�r|St|�S)N)r#rr�)r	r r r!r5�s
r5cCs||kr|�|�S|S)z4
    Pop the key if found (else return default)
    )rR)ryrr`r r r!�_popget�s
reTcCs�|dkrtjj}|�|�}|�|�}g}xf|r�|r�|d|dkr�|dkrj|�dt|d�t|��n|�d|�|�d�|�d�q*W|r�|r�d�|�||�|�Sd�|�|�|�Sn
|�|�SdS)zg
    Anything shared by pref and full will be replaced with spaces
    in full, and full returned.
    Nrr�rw)rrY�sepr�rEr�rRr�)Zpref�fullrf�indentZinclude_sep�paddingr r r!�
_space_prefix�s 

 
rjcCsR|dkrdSt|t�r t�|�}t|d�r0|jSt|d�r>|SdsNtd|��dS)Nr��__call__rz-Cannot make callable pattern object out of %r)r#rrprqr�r�rC)�patr r r!r|�s



r|cCs"xdD]\}}|�||�}qW|S)z8
    Unquote (some) entities in HTML.  (incomplete)
    ))z&nbsp;r�)z&gt;r�)z&lt;r�)z&quot;�")z&amp;r�)r�)r��ent�replr r r!r$�sr$cCs�|tkrdSt|t�s t|d�r,t|���}t|ttf�r�|r�|��}d|kr�|�d�d}|�	d���}g}x2|D]*\}}t|t
�r�|�|�}|�||f�qtW|}t
|dd�}|S)Nrwrzcharset=r4z; T)r�)rr#�dictr�r"rr�rBr�r�rr�rEr	)r�r�r%Zencoded_params�kr�r r r!r��s$

r�)N)NNT)Br�rr�rr�rrpr Zwebtest.compatrrrrrrrr	r
rrr
rrrrrrrrZwebobrrZwebtestrr�__all__�objectrr)r"r/rrrqr~r#rr&r/r0r.r:r@rBrDrErGrIrJrHr5rerjr|r$r�r r r r!�<module>	s�6[
//
1









#