U
    [hP4                     @   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   >/tmp/pip-unpacked-wheel-joqu7d3y/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 )NcheckoutZcheckincloseZclose_detached)r   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 r   )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@   z
|  W n0 t k
r: } ztd|  W 5 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   s.   t | jD ]}|d k	r
|jr
| |j q
d S r   )listr   is_validr2   rollbackr   recr   r   r   rollback_all:   s    zConnectionKiller.rollback_allc                 C   s^   t | jD ],}|d k	r
|jr
| j|j | |j q
| jD ]}| |j q>| j	  d S r   )
r3   r   r4   r   r!   dbapi_connectionr2   _checkinr5   clear)r   r7   conr   r   r   checkin_all?   s    
zConnectionKiller.checkin_allc                 C   s   |    d S r   )r=   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 r@   prepare_for_drop_tablesr(   url)r   
connectionr@   r   r   r   rC   Q   s    z(ConnectionKiller.prepare_for_drop_tablesc                 C   s   | j | }t|D ]d}t| jD ]4}|d k	r |jr |jd k	r |j|jkr | |j q t|drnt	|
  q|
  q|  d S )Nsync_engine)r   r3   r   r4   _poolr	   r2   r:   hasattrr
   disposer;   )r   r)   Zengr7   Z	proxy_refr   r   r   _drop_testing_enginesZ   s    



z&ConnectionKiller._drop_testing_enginesc                 C   s   |  d d S )Nr&   )rJ   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 5 Q R X d S r?   )r   rA   	__class__Z"__leave_connections_for_teardown__r=   rB   r@   dbconnectrC   r(   rD   )r   testr@   connr   r   r   after_test_outside_fixturesm   s    z,ConnectionKiller.after_test_outside_fixturesc                 C   s    |    | d | d d S )Nr&   r$   )r=   rJ   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   lenr;   r'   )r   lnr   r   r    stop_test_class_outside_fixtures   s    z1ConnectionKiller.stop_test_class_outside_fixturesc                 C   s"   |    | jD ]}| | qd S r   )r=   r   rJ   )r   r)   r   r   r   final_cleanup   s    
zConnectionKiller.final_cleanupc                 C   s   | j D ]}|jrdstqd S NF)r   r4   r'   r6   r   r   r   assert_all_closed   s    
z"ConnectionKiller.assert_all_closedN)__name__
__module____qualname__r   r   r   r   r*   r2   r8   r=   r>   rC   rJ   rK   rQ   rR   rV   rW   rY   r   r   r   r   r      s"   	r   c                 O   s   z| || W 5 t   X d S r   )testing_reaperrY   r0   argskwr   r   r   assert_conns_closed   s    ra   c                 O   s   z| || W 5 t   X dS )zBDecorator that rolls back all open connections after fn execution.N)r]   r8   r^   r   r   r   rollback_open_connections   s    rb   c                 O   s   t   | || dS )z:Decorator that closes all connections before fn execution.Nr]   r=   r^   r   r   r   close_first   s    rd   c                 O   s   z| || W 5 t   X dS )z9Decorator that closes all connections after fn execution.Nrc   r^   r   r   r   close_open_connections   s    re   c                 c   sX   dd l m} |jD ]@}| r$|| kr$qt||d }|sHttd| j|}| V  qd S )Nr   zsqlalchemy.dialects.%s)Zsqlalchemy.dialectsZdialects__all__getattr
__import__dialect)excludednamemodr   r   r   all_dialects   s    
 rn   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 rX   )dbapiconnections
is_stopped)r   rp   r   r   r   r      s    zReconnectFixture.__init__c                 C   s   t | j|S r   )rg   rp   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)
rp   rN   rr   r2   r   cursorexecuter'   rq   append)r   r_   kwargsrP   Zcursr   r   r   rN      s    
zReconnectFixture.connectc              
   C   s@   z
|  W n0 t k
r: } ztd|  W 5 d }~X Y nX d S )Nz.ReconnectFixture couldn't close connection: %sr+   r/   r   r   r   r2      s    
zReconnectFixture._safeFc                 C   s,   || _ t| jD ]}| |j qg | _d S r   )rr   r3   rq   r2   r   )r   stopcr   r   r   shutdown   s    zReconnectFixture.shutdownc                 C   s
   d| _ d S rX   )rr   r   r   r   r   restart   s    zReconnectFixture.restartN)F)	rZ   r[   r\   r   ru   rN   r2   r|   r}   r   r   r   r   ro      s   
ro   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 rX   )ri   rp   r|   rr   r   Z_disposer(   r   r   rI     s    
z$reconnecting_engine.<locals>.dispose)r   rM   rD   ri   rp   ro   testing_enginerI   r|   Ztest_shutdownr}   Ztest_restart)rD   optionsrp   rI   r   r   r   reconnecting_engine   s    

r   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sqliterN   c                 S   s
   d | _ d S r   )Zisolation_level)r9   Zconnection_recordr   r   r   
do_connectA  s    z"testing_engine.<locals>.do_connectbeginc                 S   s   |  d d S )NZBEGIN)Zexec_driver_sqlrP   r   r   r   do_beginE  s    z testing_engine.<locals>.do_begin)
StaticPoolr%   ) r'   Zsqlalchemy.ext.asyncior   r   rM   Z
_is_futureZsqlalchemy.futurer   
sqlalchemyZsqlalchemy.engine.urlr   poprD   Z
drivernameZdb_optscopyupdaterl   r   Zlistens_forZsqlalchemy.poolr   
isinstancer	   Z_transfer_fromrF   Z_has_eventsZ	QueuePool_timeoutZ_max_overflowr]   r*   )rD   r   futureZasyncioZtransfer_staticpoolZ_sqlite_savepointr   r   r   r)   r   Zdefault_optr(   r   r   r   r   r   r   r     sf    








r   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 r   )rx   )Zsqlar`   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]rB   )resubstr.0sr   r   r   
<listcomp>x  s     z3mock_engine.<locals>.assert_sql.<locals>.<listcomp>)r'   )Zstmtsrecvr   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 ))ri   N)r   compiler   rk   r   r   	<genexpr>}  s     z1mock_engine.<locals>.print_sql.<locals>.<genexpr>)ri   joinmockr   )r(   r   r   	print_sql{  s    zmock_engine.<locals>.print_sqlz://r   )
r   r   r   rM   rl   rH   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 r   )r(   rE   rv   )r   r(   rP   r_   ry   r   r   r   r     s    zDBAPIProxyCursor.__init__Nc                 K   s*   |r| j j||f|S | j j|f|S d S r   )rv   rw   )r   stmt
parametersr`   r   r   r   rw     s    zDBAPIProxyCursor.executec                 K   s   | j j||f|S r   )rv   executemany)r   r   paramsr`   r   r   r   r     s    zDBAPIProxyCursor.executemanyc                 C   s
   t | jS r   )iterrv   r   r   r   r   __iter__  s    zDBAPIProxyCursor.__iter__c                 C   s   t | j|S r   )rg   rv   rs   r   r   r   ru     s    zDBAPIProxyCursor.__getattr__)N)	rZ   r[   r\   __doc__r   rw   r   r   ru   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 r   )r	   Z_creatorrP   r(   
cursor_cls)r   r(   r   r   r   r   r     s    zDBAPIProxyConnection.__init__c                 O   s   | j | j| jf||S r   )r   r(   rP   )r   r_   ry   r   r   r   rv     s    zDBAPIProxyConnection.cursorc                 C   s   | j   d S r   )rP   r   r   r   r   r   r     s    zDBAPIProxyConnection.closec                 C   s   t | j|S r   )rg   rP   rs   r   r   r   ru     s    z DBAPIProxyConnection.__getattr__N)rZ   r[   r\   r   r   rv   r   ru   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 r   )r   rM   r   conn_clsr   r   r   	mock_conn  s    z"proxying_engine.<locals>.mock_connc                    s    fdd}|S )Nc                    s
    | j S r   r   )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   )r   )r   )r   r   r   r   r   r   r   proxying_engine  s    r   )N)NN)NNNFFF)N)
__future__r   r   r   r-   r   rB   r   utilr   r   r   r	   r
   objectr   r]   ra   rb   rd   re   rn   ro   r   r   r   r   r   r   r   r   r   r   <module>   sJ    

	


,
      
P
& 