B
    lbd)                 @   s   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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)	ExitStack)copy)TracebackType)	CliRunner)Client)	url_parse)Request   )
ScriptInfo)_cv_request)SessionMixin)TestResponse)Flaskc            
       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_NAMEZ	localhostZAPPLICATION_ROOT.ZPREFERRED_URL_SCHEMEz://r      ??)boolAssertionErrorZconfiggetr   ZschemeZnetloclstripr   Zquery
isinstancebytesr   super__init__)selfr   r   r   r   r   r   r   Z	http_hostZapp_rootZurlsep)	__class__ ,lib/python3.7/site-packages/flask/testing.pyr$   -   s(    


&zEnvironBuilder.__init__)objr   r   c             K   s   | j jj|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   jsondumps)r%   r*   r   r(   r(   r)   
json_dumpsU   s    zEnvironBuilder.json_dumps)r   NNN)__name__
__module____qualname____doc__strtOptionalAnyr$   r-   __classcell__r(   r(   )r'   r)   r      s      r   c                   s   e Zd ZU dZded< 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 Zdd Zdddejeeejdd fddZd dddZeje eje eje ddddZ  ZS )FlaskClienta  Works like a regular Werkzeug test client but has knowledge about
    Flask's contexts to defer the cleanup of the request context until
    the end of a ``with`` block. 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   applicationN)r   r   r   c                s:   t  j|| d| _g | _t | _ddtj d| _d S )NFz	127.0.0.1z	werkzeug/)ZREMOTE_ADDRZHTTP_USER_AGENT)	r#   r$   preserve_context_new_contextsr   _context_stackwerkzeug__version__environ_base)r%   r   r   )r'   r(   r)   r$   n   s    zFlaskClient.__init__c          
   o   s   | j dkrtd| j}|di }| j | td}|j||}|j}|	||j
}|dkrltdt|}	z
|V  W dt|	 X | }
||s||||
 |
|j
j}| j |j
j| W d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RuntimeErrorr8   
setdefaultZinject_wsgir   r   Ztest_request_contextsession_interfaceZopen_sessionrequestsetresetZresponse_classZis_null_sessionZsave_sessionZget_wsgi_headersenvironZextract_wsgi)r%   r   r   r   r?   Zouter_reqctxcrB   ZsesstokenZrespZheadersr(   r(   r)   session_transactionx   s,    





zFlaskClient.session_transactionc             C   s    | j |}| jr| jj|d< |S )Nzwerkzeug.debug.preserve_context)r>   r9   r:   append)r%   otheroutr(   r(   r)   _copy_environ   s    
zFlaskClient._copy_environc             C   s@   |  |di |d< t| jf||}z| S |  X d S )Nr>   )rM   r   r   r8   get_requestclose)r%   r   r   builderr(   r(   r)   _request_from_builder_args   s
    z&FlaskClient._request_from_builder_argsF)bufferedfollow_redirectsr   )r   rR   rS   r   r   c      	         s   |rt |d tjjttfrt |d tjjrVt|d }| |jpFi |_|	 }qt |d trtj
|d | j| i d	 }qt|d }| |j|_n| ||}| j  t j|||d}| jj|_x | jr| j }| j| qW |S )Nr   )r   r>   )rR   rS   )r!   r<   testr   dictBaseRequestr   rM   r>   rN   Zfrom_environr8   rF   rQ   r;   rO   r#   openr+   Zjson_moduler:   popenter_context)	r%   rR   rS   r   r   rP   rC   Zresponsecm)r'   r(   r)   rW      s,    



zFlaskClient.open)r   c             C   s   | j rtdd| _ | S )NzCannot nest client invocationsT)r9   r@   )r%   r(   r(   r)   	__enter__   s    zFlaskClient.__enter__)exc_type	exc_valuetbr   c             C   s   d| _ | j  d S )NF)r9   r;   rO   )r%   r\   r]   r^   r(   r(   r)   __exit__   s    zFlaskClient.__exit__)r.   r/   r0   r1   __annotations__r3   r5   r$   r   	Generatorr   rI   rM   rQ   r   rW   r[   r4   typeBaseExceptionr   r_   r6   r(   r(   )r'   r)   r7   ^   s"   

4'r7   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(   r)   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.
        Nr*   c                  s    j S )N)r   r(   )r%   r(   r)   <lambda>      z'FlaskCliRunner.invoke.<locals>.<lambda>)Z
create_app)r   re   r   r#   invoke)r%   re   r   r   )r'   )r%   r)   rh     s
    zFlaskCliRunner.invoke)NN)	r.   r/   r0   r1   r3   r5   r$   rh   r6   r(   r(   )r'   r)   rd      s   rd   ) typingr3   
contextlibr   r   r   typesr   Zwerkzeug.testr<   Zclick.testingr   r   Zwerkzeug.urlsr   Zwerkzeug.wrappersr	   rV   re   r   globalsr   Zsessionsr   ZTYPE_CHECKINGr   r   r   rT   r   r7   rd   r(   r(   r(   r)   <module>   s&   G  