U
    Ha)(                     @   s   d dl Zd dlmZ d dlmZ d dlmZ d dlZd dl	m
Z
 d dlmZ d dlmZ d dlmZ d	d
lmZ d	dlmZ d	dlmZ d	dlmZ ejrd	dlmZ d	dlmZ G dd dejj Z G dd deZ!G dd de
Z"dS )    N)contextmanager)copy)TracebackType)	CliRunner)Client)	url_parse)Request   )_request_ctx_stack)
ScriptInfo)dumps)SessionMixin)Flask)Responsec                
       sb   e Zd ZdZddeeje eje eje ejejdd fddZejejedd	d
Z	  Z
S )EnvironBuildera  An :class:`~werkzeug.test.EnvironBuilder`, that takes defaults from the
    application.

    :param app: The Flask application to configure the environment from.
    :param path: URL path being requested.
    :param base_url: Base URL where the app is being served, which
        ``path`` is relative to. If not given, built from
        :data:`PREFERRED_URL_SCHEME`, ``subdomain``,
        :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
    :param subdomain: Subdomain name to append to :data:`SERVER_NAME`.
    :param url_scheme: Scheme to use instead of
        :data:`PREFERRED_URL_SCHEME`.
    :param json: If given, this is serialized as JSON and passed as
        ``data``. Also defaults ``content_type`` to
        ``application/json``.
    :param args: other positional arguments passed to
        :class:`~werkzeug.test.EnvironBuilder`.
    :param kwargs: other keyword arguments passed to
        :class:`~werkzeug.test.EnvironBuilder`.
    /Nr   )apppathbase_url	subdomain
url_schemeargskwargsreturnc                    s   |s|s|r(|d k	t |p|ks(td|d kr|jdp>d}|jd }	|r\| d| }|d krn|jd }t|}
|
jp~| d|
jp| d|	d }|
j}|
j	rt
|
j	trd	nd
}|||
j	 7 }|| _t j||f|| d S )Nz8Cannot pass "subdomain" or "url_scheme" with "base_url".ZSERVER_NAME	localhostZAPPLICATION_ROOT.ZPREFERRED_URL_SCHEMEz://r      ??)boolAssertionErrorconfiggetr   schemenetloclstripr   query
isinstancebytesr   super__init__)selfr   r   r   r   r   r   r   Z	http_hostZapp_rooturlsep	__class__ 1/tmp/pip-unpacked-wheel-99zf6fhi/flask/testing.pyr)   ,   s0    


$zEnvironBuilder.__init__)objr   r   c                 K   s   | d| j t|f|S )zSerialize ``obj`` to a JSON-formatted string.

        The serialization will be configured according to the config associated
        with this EnvironBuilder's ``app``.
        r   )
setdefaultr   
json_dumps)r*   r1   r   r/   r/   r0   r3   T   s    zEnvironBuilder.json_dumps)r   NNN)__name__
__module____qualname____doc__strtOptionalAnyr)   r3   __classcell__r/   r/   r-   r0   r      s        (r   c                       s   e Zd ZU dZded< dZejejdd fddZe	ejejej
eddf dd	d
Zddddejeeeejdd fddZd dddZeeeddddZ  ZS )FlaskClientaE  Works like a regular Werkzeug test client but has some knowledge about
    how Flask works to defer the cleanup of the request context stack to the
    end of a ``with`` body when used in a ``with`` statement.  For general
    information about how to use this class refer to
    :class:`werkzeug.test.Client`.

    .. versionchanged:: 0.12
       `app.test_client()` includes preset default environment, which can be
       set after instantiation of the `app.test_client()` object in
       `client.environ_base`.

    Basic usage is outlined in the :doc:`/testing` chapter.
    r   applicationFN)r   r   r   c                    s&   t  j|| ddtj d| _d S )Nz	127.0.0.1z	werkzeug/)ZREMOTE_ADDRZHTTP_USER_AGENT)r(   r)   werkzeug__version__environ_base)r*   r   r   r-   r/   r0   r)   p   s    
zFlaskClient.__init__c              	   o   s   | j dkrtd| j}|di }| j | tj}|j||}|j}|	||j
}|dkrhtdt| z
|V  W 5 t  X | }	||s||||	 |	|j
j}
| j |j
j|
 W 5 Q R X dS )a  When used in combination with a ``with`` statement this opens a
        session transaction.  This can be used to modify the session that
        the test client uses.  Once the ``with`` block is left the session is
        stored back.

        ::

            with client.session_transaction() as session:
                session['value'] = 42

        Internally this is implemented by going through a temporary test
        request context and since session handling could depend on
        request variables this function accepts the same arguments as
        :meth:`~flask.Flask.test_request_context` which are directly
        passed through.
        Nz:Session transactions only make sense with cookies enabled.environ_overridesz?Session backend did not open a session. Check the configuration)Z
cookie_jarRuntimeErrorr>   r2   Zinject_wsgir
   topZtest_request_contextsession_interfaceZopen_sessionrequestpushpopresponse_classZis_null_sessionZsave_sessionZget_wsgi_headersenvironZextract_wsgi)r*   r   r   r   rB   Zouter_reqctxcrE   sessrespheadersr/   r/   r0   session_transactionw   s0    




zFlaskClient.session_transactionas_tuplebufferedfollow_redirectsr   )r   rQ   rR   rS   r   r   c          
         s   d } fdd}|st |dkr|d }t|tjjrXt|}	||	jpHi |	_|	 }nDt|tr~tj	| j
|i d }nt|trt|}||j|_|d kr||di |d< t j
f||}	z|	 }W 5 |	  X t j||||dS )Nc                    s    j | d jiS )Nzflask._preserve_context)rA   preserve_context)otherr*   r/   r0   copy_environ   s
     z&FlaskClient.open.<locals>.copy_environr	   r   )r   rA   rA   rP   )lenr&   r?   testr   r   rA   get_requestdictZfrom_environr>   BaseRequestrJ   r!   closer(   open)
r*   rQ   rR   rS   r   r   rF   rW   argZbuilderr-   rV   r0   r^      s:    	

  

zFlaskClient.open)r   c                 C   s   | j rtdd| _ | S )NzCannot nest client invocationsT)rT   rC   rV   r/   r/   r0   	__enter__   s    zFlaskClient.__enter__)exc_type	exc_valuetbr   c                 C   s,   d| _ tj}|d k	r(|jr(|  qq(qd S )NF)rT   r
   rD   Z	preservedrH   )r*   ra   rb   rc   rD   r/   r/   r0   __exit__   s
    
zFlaskClient.__exit__)r4   r5   r6   r7   __annotations__rT   r9   r;   r)   r   	Generatorr   rO   r   r^   r`   typeBaseExceptionr   rd   r<   r/   r/   r-   r0   r=   ^   s4   
 91  r=   c                       sN   e Zd ZdZdejdd fddZd
ejejejejd fdd	Z  ZS )FlaskCliRunnerzA :class:`~click.testing.CliRunner` for testing a Flask app's
    CLI commands. Typically created using
    :meth:`~flask.Flask.test_cli_runner`. See :ref:`testing-cli`.
    r   N)r   r   r   c                    s   || _ t jf | d S N)r   r(   r)   )r*   r   r   r-   r/   r0   r)      s    zFlaskCliRunner.__init__)clir   r   r   c                    s@   |dkr j j}d|kr.t fddd|d< t j||f|S )ac  Invokes a CLI command in an isolated environment. See
        :meth:`CliRunner.invoke <click.testing.CliRunner.invoke>` for
        full method documentation. See :ref:`testing-cli` for examples.

        If the ``obj`` argument is not given, passes an instance of
        :class:`~flask.cli.ScriptInfo` that knows how to load the Flask
        app being tested.

        :param cli: Command object to invoke. Default is the app's
            :attr:`~flask.app.Flask.cli` group.
        :param args: List of strings to invoke the command with.

        :return: a :class:`~click.testing.Result` object.
        Nr1   c                      s    j S rj   )r   r/   rV   r/   r0   <lambda>      z'FlaskCliRunner.invoke.<locals>.<lambda>)Z
create_app)r   rk   r   r(   invoke)r*   rk   r   r   r-   rV   r0   rn     s
    zFlaskCliRunner.invoke)NN)	r4   r5   r6   r7   r9   r;   r)   rn   r<   r/   r/   r-   r0   ri      s        ri   )#typingr9   
contextlibr   r   typesr   Zwerkzeug.testr?   Zclick.testingr   r   Zwerkzeug.urlsr   Zwerkzeug.wrappersr   r\    r
   rk   r   jsonr   r3   sessionsr   TYPE_CHECKINGr   r   wrappersr   rY   r   r=   ri   r/   r/   r/   r0   <module>   s&   H 