B
    KLcP4                 @   s$  d dl mZ d dlZd dlZd dl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 G dd deZe Ze	dd Ze	dd Ze	dd Ze	dd Zd&ddZG dd deZd'ddZd(ddZd)ddZG d d! d!eZG d"d# d#eZeefd$d%ZdS )*    )absolute_importN   )config)	decorator)
gc_collect   )event)pool)
await_onlyc               @   s   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#S )$ConnectionKillerc             C   s"   t  | _tt| _t | _d S )N)weakrefWeakKeyDictionary
proxy_refscollectionsdefaultdictsettesting_enginesdbapi_connections)self r   9lib/python3.7/site-packages/sqlalchemy/testing/engines.py__init__   s    
zConnectionKiller.__init__c             C   sD   t |d| j t |d| j t |d| j t |d| j d S )NZcheckoutZcheckincloseZclose_detached)r   Zlisten	_add_conn_remove_conn)r   r	   r   r   r   add_pool   s    zConnectionKiller.add_poolc             C   s   | j | d| j|< d S )NT)r   addr   )r   Z	dbapi_conZ
con_recordZ	con_proxyr   r   r   r   %   s    zConnectionKiller._add_connc             G   s   | j | d S )N)r   discard)r   
dbapi_connargr   r   r   r   )   s    zConnectionKiller._remove_connc             C   s,   |  |j |dkst| j| | d S )N)classglobalfunctionZfixture)r   r	   AssertionErrorr   r   )r   enginescoper   r   r   
add_engine,   s    zConnectionKiller.add_enginec          
   C   s@   y
|  W n0 t k
r: } ztd|  W d d }~X Y nX d S )Nz5testing_reaper couldn't rollback/close connection: %s)	Exceptionwarningswarn)r   fner   r   r   _safe2   s
    
zConnectionKiller._safec             C   s2   x,t | jD ]}|d k	r|jr| |j qW d S )N)listr   is_validr,   rollback)r   recr   r   r   rollback_all:   s    zConnectionKiller.rollback_allc             C   sf   x:t | jD ],}|d k	r|jr| j|j | |j qW x| jD ]}| |j qDW | j	  d S )N)
r-   r   r.   r   r   dbapi_connectionr,   _checkinr/   clear)r   r0   Zconr   r   r   checkin_all?   s    zConnectionKiller.checkin_allc             C   s   |    d S )N)r5   )r   r   r   r   	close_allN   s    zConnectionKiller.close_allc             C   s*   t js
d S ddlm} ||jj| d S )Nr   )	provision)r   bootstrapped_as_sqlalchemy r7   prepare_for_drop_tablesr$   url)r   
connectionr7   r   r   r   r:   Q   s    z(ConnectionKiller.prepare_for_drop_tablesc             C   s   | j | }xtt|D ]h}xBt| jD ]4}|d k	r$|jr$|jd k	r$|j|jkr$| |j q$W t|drtt	|
  q|
  qW |  d S )Nsync_engine)r   r-   r   r.   Z_poolr	   r,   r3   hasattrr
   disposer4   )r   r%   Zengr0   Z	proxy_refr   r   r   _drop_testing_enginesZ   s    


z&ConnectionKiller._drop_testing_enginesc             C   s   |  d d S )Nr"   )r@   )r   r   r   r   
after_testj   s    zConnectionKiller.after_testc          	   C   sT   t js
d S |jjrd S |   ddlm} t j }|	|j
j| W d Q R X d S )Nr   )r7   )r   r8   	__class__Z"__leave_connections_for_teardown__r5   r9   r7   dbconnectr:   r$   r;   )r   Ztestr7   connr   r   r   after_test_outside_fixturesm   s    z,ConnectionKiller.after_test_outside_fixturesc             C   s    |    | d | d d S )Nr"   r    )r5   r@   )r   r   r   r   stop_test_class_inside_fixtures   s    
z0ConnectionKiller.stop_test_class_inside_fixturesc             C   sB   t jjr>t  t jjr>tt jj}t jj  ds>td| d S )NFz/%d connection recs not cleared after test suite)r	   baseZ_strong_ref_connection_recordsr   lenr4   r#   )r   Zlnr   r   r    stop_test_class_outside_fixtures   s    z1ConnectionKiller.stop_test_class_outside_fixturesc             C   s&   |    x| jD ]}| | qW d S )N)r5   r   r@   )r   r%   r   r   r   final_cleanup   s    zConnectionKiller.final_cleanupc             C   s"   x| j D ]}|jrdstqW d S )NF)r   r.   r#   )r   r0   r   r   r   assert_all_closed   s    z"ConnectionKiller.assert_all_closedN)__name__
__module____qualname__r   r   r   r   r&   r,   r1   r5   r6   r:   r@   rA   rF   rG   rJ   rK   rL   r   r   r   r   r      s"   	r   c             O   s   z| || W d t   X d S )N)testing_reaperrL   )r*   argskwr   r   r   assert_conns_closed   s    rS   c             O   s   z| || W dt   X dS )zBDecorator that rolls back all open connections after fn execution.N)rP   r1   )r*   rQ   rR   r   r   r   rollback_open_connections   s    rT   c             O   s   t   | || dS )z:Decorator that closes all connections before fn execution.N)rP   r5   )r*   rQ   rR   r   r   r   close_first   s    rU   c             O   s   z| || W dt   X dS )z9Decorator that closes all connections after fn execution.N)rP   r5   )r*   rQ   rR   r   r   r   close_open_connections   s    rV   c             c   s\   dd l m} xJ|jD ]@}| r&|| kr&qt||d }|sJttd| j|}| V  qW d S )Nr   zsqlalchemy.dialects.%s)Zsqlalchemy.dialectsZdialects__all__getattr
__import__dialect)Zexcludednamemodr   r   r   all_dialects   s    r^   c               @   s>   e Zd Zdd Zdd Zdd Zdd Zdd
dZdd ZdS )ReconnectFixturec             C   s   || _ g | _d| _d S )NF)dbapiconnections
is_stopped)r   r`   r   r   r   r      s    zReconnectFixture.__init__c             C   s   t | j|S )N)rX   r`   )r   keyr   r   r   __getattr__   s    zReconnectFixture.__getattr__c             O   sT   | j j||}| jr@| |j | }|d dsPtdn| j	| |S d S )Nzselect 1Fz%simulated connect failure didn't work)
r`   rD   rb   r,   r   cursorexecuter#   ra   append)r   rQ   kwargsrE   Zcursr   r   r   rD      s    
zReconnectFixture.connectc          
   C   s@   y
|  W n0 t k
r: } ztd|  W d d }~X Y nX d S )Nz.ReconnectFixture couldn't close connection: %s)r'   r(   r)   )r   r*   r+   r   r   r   r,      s    
zReconnectFixture._safeFc             C   s0   || _ xt| jD ]}| |j qW g | _d S )N)rb   r-   ra   r,   r   )r   stopcr   r   r   shutdown   s    zReconnectFixture.shutdownc             C   s
   d| _ d S )NF)rb   )r   r   r   r   restart   s    zReconnectFixture.restartN)F)	rM   rN   rO   r   rd   rD   r,   rk   rl   r   r   r   r   r_      s   
r_   c                sj   | p
t jj} t jjj}|si }t||d< t| |j  fdd}jjj_	jjj
_|_S )Nmodulec                  s    j j  dj j_   d S )NF)rZ   r`   rk   rb   r   )_disposer$   r   r   r?     s    
z$reconnecting_engine.<locals>.dispose)r   rC   r;   rZ   r`   r_   testing_enginer?   rk   Ztest_shutdownrl   Ztest_restart)r;   optionsr`   r?   r   )rn   r$   r   reconnecting_engine   s    

rq   Fc             C   s  |r|rt ddlm} n4|s4tjrBtjjrB|dk	rBddlm} nddlm} ddl	m
} |sld}d}	d}
n$|dd}|d	d}	|d
d}
| ptjj} || } |dkrtjdks| jtjjjkrtj}ni }n2tjdk	r| jtjjjkrtj }|| || f|}|
rL|jdkrLt|ddd }t|ddd }|rddlm} tjdk	rttjj|rd}|jtjj |	dkr|rd|j_nd|_t|jtjrd|j_d|j_|rt||	 |S )zBProduce an engine configured by --options with optional overrides.r   )create_async_engineF)create_engine)make_urlTr"   
use_reaperr%   sqlite_savepointNZsqliterD   c             S   s
   d | _ d S )N)Zisolation_level)r2   Zconnection_recordr   r   r   
do_connectA  s    z"testing_engine.<locals>.do_connectZbeginc             S   s   |  d d S )NZBEGIN)Zexec_driver_sql)rE   r   r   r   do_beginE  s    z testing_engine.<locals>.do_begin)
StaticPoolr!   ) r#   Zsqlalchemy.ext.asynciorr   r   rC   Z
_is_futureZsqlalchemy.futurers   
sqlalchemyZsqlalchemy.engine.urlrt   popr;   Z
drivernameZdb_optscopyupdater\   r   Zlistens_forZsqlalchemy.poolry   
isinstancer	   Z_transfer_fromr=   Z_has_eventsZ	QueuePoolZ_timeoutZ_max_overflowrP   r&   )r;   rp   ZfutureZasyncioZtransfer_staticpoolZ_sqlite_savepointrs   rt   ru   r%   rv   Zdefault_optr$   rw   rx   ry   r   r   r   ro     sV    




ro   c                sr   ddl m} | stjj} g   fdd} fdd}fdd}|| d	 |td
r\t _|_|_	S )a'  Provides a mocking engine based on the current testing.db.

    This is normally used to test DDL generation flow as emitted
    by an Engine.

    It should not be used in other cases, as assert_compile() and
    assert_sql_execution() are much better choices with fewer
    moving parts.

    r   )create_mock_enginec                s     |  d S )N)rg   )ZsqlarR   )bufferr   r   executort  s    zmock_engine.<locals>.executorc                s"   dd  D }|| kst |d S )Nc             S   s   g | ]}t d dt|qS )z[\n\t]r9   )resubstr).0sr   r   r   
<listcomp>x  s    z3mock_engine.<locals>.assert_sql.<locals>.<listcomp>)r#   )ZstmtsZrecv)r   r   r   
assert_sqlw  s    zmock_engine.<locals>.assert_sqlc                  s    j  d fddjD S )N
c             3   s   | ]}t |j d V  qdS ))rZ   N)r   compile)r   r   )r[   r   r   	<genexpr>}  s    z1mock_engine.<locals>.print_sql.<locals>.<genexpr>)rZ   joinmockr   )r$   )r[   r   	print_sql{  s    zmock_engine.<locals>.print_sqlz://r   )
rz   r   r   rC   r\   r>   r#   r   r   r   )Zdialect_namer   r   r   r   r   )r   r$   r   mock_enginea  s    r   c               @   s:   e Zd ZdZdd ZdddZdd Zd	d
 Zdd ZdS )DBAPIProxyCursorzuProxy a DBAPI cursor.

    Tests can provide subclasses of this to intercept
    DBAPI-level cursor operations.

    c             O   s   || _ || _|j||| _d S )N)r$   r<   re   )r   r$   rE   rQ   rh   r   r   r   r     s    zDBAPIProxyCursor.__init__Nc             K   s*   |r| j j||f|S | j j|f|S d S )N)re   rf   )r   stmtZ
parametersrR   r   r   r   rf     s    zDBAPIProxyCursor.executec             K   s   | j j||f|S )N)re   executemany)r   r   ZparamsrR   r   r   r   r     s    zDBAPIProxyCursor.executemanyc             C   s
   t | jS )N)iterre   )r   r   r   r   __iter__  s    zDBAPIProxyCursor.__iter__c             C   s   t | j|S )N)rX   re   )r   rc   r   r   r   rd     s    zDBAPIProxyCursor.__getattr__)N)	rM   rN   rO   __doc__r   rf   r   r   rd   r   r   r   r   r     s   
r   c               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )DBAPIProxyConnectionz}Proxy a DBAPI connection.

    Tests can provide subclasses of this to intercept
    DBAPI-level connection operations.

    c             C   s   |j  | _|| _|| _d S )N)r	   Z_creatorrE   r$   
cursor_cls)r   r$   r   r   r   r   r     s    zDBAPIProxyConnection.__init__c             O   s   | j | j| jf||S )N)r   r$   rE   )r   rQ   rh   r   r   r   re     s    zDBAPIProxyConnection.cursorc             C   s   | j   d S )N)rE   r   )r   r   r   r   r     s    zDBAPIProxyConnection.closec             C   s   t | j|S )N)rX   rE   )r   rc   r   r   r   rd     s    z DBAPIProxyConnection.__getattr__N)rM   rN   rO   r   r   re   r   rd   r   r   r   r   r     s
   r   c                s&    fdd}dd }t ||ddS )zIProduce an engine that provides proxy hooks for
    common methods.

    c                  s    t jS )N)r   rC   r   )conn_clsr   r   r   	mock_conn  s    z"proxying_engine.<locals>.mock_connc                s    fdd}|S )Nc                s
    | j S )N)rE   )r   )do_on_connectr   r   go  s    z8proxying_engine.<locals>._wrap_do_on_connect.<locals>.gor   )r   r   r   )r   r   _wrap_do_on_connect  s    z,proxying_engine.<locals>._wrap_do_on_connect)Zcreatorr   )rp   )ro   )r   r   r   r   r   )r   r   r   proxying_engine  s
    r   )N)NN)NNNFFF)N)Z
__future__r   r   r   r(   r   r9   r   utilr   r   r   r	   r
   objectr   rP   rS   rT   rU   rV   r^   r_   rq   ro   r   r   r   r   r   r   r   r   <module>   s<    
	
,
     
J
&