o
    ¯bA  ã                   @   sf   d Z ddlmZ ddlmZmZ G dd„ deƒZG dd„ dƒZG dd	„ d	ƒZ	G d
d„ dƒZ
d	dgZdS )zg
An asynchronous mapping to U{DB-API
2.0<http://www.python.org/topics/database/DatabaseAPI-2.0.html>}.
é    )Úthreads)ÚlogÚreflectc                   @   s   e Zd ZdZdS )ÚConnectionLostzb
    This exception means that a db connection has been lost.  Client code may
    try again.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r
   r
   ú;/usr/lib/python3/dist-packages/twisted/enterprise/adbapi.pyr      s    r   c                   @   s8   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ ZdS )Ú
Connectiona  
    A wrapper for a DB-API connection instance.

    The wrapper passes almost everything to the wrapped connection and so has
    the same API. However, the L{Connection} knows about its pool and also
    handle reconnecting should when the real connection dies.
    c                 C   s   || _ d | _|  ¡  d S ©N)Ú_poolÚ_connectionÚ	reconnect)ÚselfÚpoolr
   r
   r   Ú__init__   ó   zConnection.__init__c                 C   s   d S r   r
   ©r   r
   r
   r   Úclose$   s   zConnection.closec                 C   s–   | j js| j ¡  d S z| j ¡  | j ¡ }| | j j¡ | ¡  | j ¡  W d S  t	y7   t
 d d¡ Y nw | j  | j¡ | j jrHt
 d¡ tƒ ‚)NúRollback failedzConnection lost.)r   r   r   ÚrollbackÚcursorÚexecuteÚgood_sqlr   ÚcommitÚBaseExceptionr   ÚerrÚ
disconnectÚnoisyÚmsgr   )r   Úcursr
   r
   r   r   .   s"   



ÿ
zConnection.rollbackc                 C   s(   | j d ur| j | j ¡ | j ¡ | _ d S r   )r   r   r   Úconnectr   r
   r
   r   r   D   s   
zConnection.reconnectc                 C   ó   t | j|ƒS r   )Úgetattrr   ©r   Únamer
   r
   r   Ú__getattr__I   ó   zConnection.__getattr__N)	r   r   r   r	   r   r   r   r   r(   r
   r
   r
   r   r      s    
r   c                   @   s<   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dS )ÚTransactiona  
    A lightweight wrapper for a DB-API 'cursor' object.

    Relays attribute access to the DB cursor. That is, you can call
    C{execute()}, C{fetchall()}, etc., and they will be called on the
    underlying DB-API cursor object. Attributes will also be retrieved from
    there.
    Nc                 C   s   || _ || _|  ¡  d S r   )r   r   Úreopen)r   r   Ú
connectionr
   r
   r   r   Y   r   zTransaction.__init__c                 C   s   | j }d | _ | ¡  d S r   )Ú_cursorr   )r   r-   r
   r
   r   r   ^   r   zTransaction.closec                 C   sx   | j d ur	|  ¡  z	| j ¡ | _ W d S  ty&   | jjs‚ t d d¡ Y nw | jj	r0t 
d¡ |  ¡  | j ¡ | _ d S )NzCursor creation failedzConnection lost, reconnecting)r-   r   r   r   r   r   r   r   r   r    r!   r   r
   r
   r   r+   c   s   
ü
zTransaction.reopenc                 C   s   | j  ¡  d | _d S r   )r   r   r-   r   r
   r
   r   r   v   s   

zTransaction.reconnectc                 C   r$   r   )r%   r-   r&   r
   r
   r   r(   z   r)   zTransaction.__getattr__)
r   r   r   r	   r-   r   r   r+   r   r(   r
   r
   r
   r   r*   M   s    	r*   c                   @   sÔ   e Zd ZdZd ¡ ZdZdZdZdZ	dZ
dZdZdZeZ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*d+„ Z$dS ),ÚConnectionPoolaŠ  
    Represent a pool of connections to a DB-API 2.0 compliant database.

    @ivar connectionFactory: factory for connections, default to L{Connection}.
    @type connectionFactory: any callable.

    @ivar transactionFactory: factory for transactions, default to
        L{Transaction}.
    @type transactionFactory: any callable

    @ivar shutdownID: L{None} or a handle on the shutdown event trigger which
        will be used to stop the connection pool workers when the reactor
        stops.

    @ivar _reactor: The reactor which will be used to schedule startup and
        shutdown events.
    @type _reactor: L{IReactorCore} provider
    z-min max name noisy openfun reconnect good_sqlFé   é   Nzselect 1c           	      O   s  || _ t |¡| _t| jddƒdkrt d¡ t| jddƒdk r%t d¡ | d	d¡}|du r5dd
lm	} || _
|| _|| _| jD ]}d|› �}||v rWt| ||| ƒ ||= qAt| j| jƒ| _t| j| jƒ| _i | _ddlm}m} |j| _| | j| j¡| _| j
 | j¡| _dS )aÈ  
        Create a new L{ConnectionPool}.

        Any positional or keyword arguments other than those documented here
        are passed to the DB-API object when connecting. Use these arguments to
        pass database names, usernames, passwords, etc.

        @param dbapiName: an import string to use to obtain a DB-API compatible
            module (e.g. C{'pyPgSQL.PgSQL'})

        @keyword cp_min: the minimum number of connections in pool (default 3)

        @keyword cp_max: the maximum number of connections in pool (default 5)

        @keyword cp_noisy: generate informational log messages during operation
            (default C{False})

        @keyword cp_openfun: a callback invoked after every C{connect()} on the
            underlying DB-API object. The callback is passed a new DB-API
            connection object. This callback can setup per-connection state
            such as charset, timezone, etc.

        @keyword cp_reconnect: detect connections which have failed and reconnect
            (default C{False}). Failed connections may result in
            L{ConnectionLost} exceptions, which indicate the query may need to
            be re-sent.

        @keyword cp_good_sql: an sql query which should always succeed and change
            no state (default C{'select 1'})

        @keyword cp_reactor: use this reactor instead of the global reactor
            (added in Twisted 10.2).
        @type cp_reactor: L{IReactorCore} provider
        ÚapilevelNz2.0z'DB API module not DB API 2.0 compliant.Úthreadsafetyr   é   z+DB API module not sufficiently thread-safe.Ú
cp_reactor)ÚreactorÚcp_)Ú
threadableÚ
threadpool)Ú	dbapiNamer   ÚnamedModuleÚdbapir%   r   r!   ÚpopÚtwisted.internetr5   Ú_reactorÚconnargsÚconnkwÚCP_ARGSÚsetattrÚminÚmaxÚconnectionsÚtwisted.pythonr7   r8   ÚgetThreadIDÚthreadIDÚ
ThreadPoolÚcallWhenRunningÚ_startÚstartID)	r   r9   r?   r@   r5   ÚargÚcpArgr7   r8   r
   r
   r   r   ¤   s2   #



€zConnectionPool.__init__c                 C   s   d | _ |  ¡ S r   )rL   Ústartr   r
   r
   r   rK   ë   s   zConnectionPool._startc                 C   s2   | j s| j ¡  | j dd| j¡| _d| _ dS dS )z�
        Start the connection pool.

        If you are using the reactor normally, this function does *not*
        need to be called.
        ÚduringÚshutdownTN)Úrunningr8   rO   r>   ÚaddSystemEventTriggerÚ
finalCloseÚ
shutdownIDr   r
   r
   r   rO   ï   s   
ÿ
ûzConnectionPool.startc                 O   ó$   t j| j| j| j|g|¢R i |¤ŽS )aý  
        Execute a function with a database connection and return the result.

        @param func: A callable object of one argument which will be executed
            in a thread with a connection from the pool. It will be passed as
            its first argument a L{Connection} instance (whose interface is
            mostly identical to that of a connection object for your DB-API
            module of choice), and its results will be returned as a
            L{Deferred}. If the method raises an exception the transaction will
            be rolled back. Otherwise, the transaction will be committed.
            B{Note} that this function is B{not} run in the main thread: it
            must be threadsafe.

        @param args: positional arguments to be passed to func

        @param kw: keyword arguments to be passed to func

        @return: a L{Deferred} which will fire the return value of
            C{func(Transaction(...), *args, **kw)}, or a
            L{twisted.python.failure.Failure}.
        )r   ÚdeferToThreadPoolr>   r8   Ú_runWithConnection)r   ÚfuncÚargsÚkwr
   r
   r   ÚrunWithConnectioný   s   ÿÿÿz ConnectionPool.runWithConnectionc                 O   sj   |   | ¡}z||g|¢R i |¤Ž}| ¡  |W S  ty4   z| ¡  W ‚  ty3   t d d¡ Y ‚ w w ©Nr   )ÚconnectionFactoryr   r   r   r   r   )r   rY   rZ   r[   ÚconnÚresultr
   r
   r   rX     s   

þþýz!ConnectionPool._runWithConnectionc                 O   rV   )aÈ  
        Interact with the database and return the result.

        The 'interaction' is a callable object which will be executed in a
        thread using a pooled connection. It will be passed an L{Transaction}
        object as an argument (whose interface is identical to that of the
        database cursor for your DB-API module of choice), and its results will
        be returned as a L{Deferred}. If running the method raises an
        exception, the transaction will be rolled back. If the method returns a
        value, the transaction will be committed.

        NOTE that the function you pass is *not* run in the main thread: you
        may have to worry about thread-safety in the function you pass to this
        if it tries to use non-local objects.

        @param interaction: a callable object whose first argument is an
            L{adbapi.Transaction}.

        @param args: additional positional arguments to be passed to
            interaction

        @param kw: keyword arguments to be passed to interaction

        @return: a Deferred which will fire the return value of
            C{interaction(Transaction(...), *args, **kw)}, or a
            L{twisted.python.failure.Failure}.
        )r   rW   r>   r8   Ú_runInteraction)r   ÚinteractionrZ   r[   r
   r
   r   ÚrunInteraction$  s   üûúzConnectionPool.runInteractionc                 O   ó   | j | jg|¢R i |¤ŽS )aY  
        Execute an SQL query and return the result.

        A DB-API cursor which will be invoked with C{cursor.execute(*args,
        **kw)}. The exact nature of the arguments will depend on the specific
        flavor of DB-API being used, but the first argument in C{*args} be an
        SQL statement. The result of a subsequent C{cursor.fetchall()} will be
        fired to the L{Deferred} which is returned. If either the 'execute' or
        'fetchall' methods raise an exception, the transaction will be rolled
        back and a L{twisted.python.failure.Failure} returned.

        The C{*args} and C{**kw} arguments will be passed to the DB-API
        cursor's 'execute' method.

        @return: a L{Deferred} which will fire the return value of a DB-API
            cursor's 'fetchall' method, or a L{twisted.python.failure.Failure}.
        )rc   Ú	_runQuery©r   rZ   r[   r
   r
   r   ÚrunQueryI  s   zConnectionPool.runQueryc                 O   rd   )aK  
        Execute an SQL query and return L{None}.

        A DB-API cursor which will be invoked with C{cursor.execute(*args,
        **kw)}. The exact nature of the arguments will depend on the specific
        flavor of DB-API being used, but the first argument in C{*args} will be
        an SQL statement. This method will not attempt to fetch any results
        from the query and is thus suitable for C{INSERT}, C{DELETE}, and other
        SQL statements which do not return values. If the 'execute' method
        raises an exception, the transaction will be rolled back and a
        L{Failure} returned.

        The C{*args} and C{*kw} arguments will be passed to the DB-API cursor's
        'execute' method.

        @return: a L{Deferred} which will fire with L{None} or a
            L{twisted.python.failure.Failure}.
        )rc   Ú_runOperationrf   r
   r
   r   ÚrunOperation]  s   zConnectionPool.runOperationc                 C   s@   | j r| j | j ¡ d| _ | jr| j | j¡ d| _|  ¡  dS )zC
        Close all pool connections and shutdown the pool.
        N)rU   r>   ÚremoveSystemEventTriggerrL   rT   r   r
   r
   r   r   r  s   zConnectionPool.closec                 C   s>   d| _ | j ¡  d| _| j ¡ D ]}|  |¡ q| j ¡  dS )zE
        This should only be called by the shutdown trigger.
        NF)rU   r8   ÚstoprR   rE   ÚvaluesÚ_closeÚclear©r   r_   r
   r
   r   rT   ~  s   
zConnectionPool.finalClosec                 C   sl   |   ¡ }| j |¡}|du r4| jrt d| j› �¡ | jj| j	i | j
¤Ž}| jdur/|  |¡ || j|< |S )a•  
        Return a database connection when one becomes available.

        This method blocks and should be run in a thread from the internal
        threadpool. Don't call this method directly from non-threaded code.
        Using this method outside the external threadpool may exceed the
        maximum number of connections in the pool.

        @return: a database connection from the pool.
        Nzadbapi connecting: )rH   rE   Úgetr    r   r!   r9   r;   r#   r?   r@   Úopenfun)r   Útidr_   r
   r
   r   r#   ‰  s   


zConnectionPool.connectc                 C   sB   |   ¡ }|| j |¡urtdƒ‚|dur|  |¡ | j|= dS dS )a  
        Disconnect a database connection associated with this pool.

        Note: This function should only be used by the same thread which called
        L{ConnectionPool.connect}. As with C{connect}, this function is not
        used in normal non-threaded Twisted code.
        zwrong connection for threadN)rH   rE   rp   Ú	Exceptionrm   )r   r_   rr   r
   r
   r   r      s   
þzConnectionPool.disconnectc                 C   sH   | j rt d| j› �¡ z| ¡  W d S  ty#   t d d¡ Y d S w )Nzadbapi closing: zConnection close failed)r    r   r!   r9   r   r   r   ro   r
   r
   r   rm   ¯  s   ÿzConnectionPool._closec                 O   s~   |   | ¡}|  | |¡}z||g|¢R i |¤Ž}| ¡  | ¡  |W S  ty>   z| ¡  W ‚  ty=   t d d¡ Y ‚ w w r]   )r^   ÚtransactionFactoryr   r   r   r   r   r   )r   rb   rZ   r[   r_   Útransr`   r
   r
   r   ra   ·  s    

þþýzConnectionPool._runInteractionc                 O   s   |j |i |¤Ž | ¡ S r   )r   Úfetchall©r   ru   rZ   r[   r
   r
   r   re   Æ  s   zConnectionPool._runQueryc                 O   s   |j |i |¤Ž d S r   )r   rw   r
   r
   r   rh   Ê  s   zConnectionPool._runOperationc              	   C   s&   | j | j| j| j| j| j| j| jdœS )N©r9   rC   rD   r    r   r   r?   r@   rx   r   r
   r
   r   Ú__getstate__Í  s   øzConnectionPool.__getstate__c                 C   s(   || _ | j| jg| j¢R i | j¤Ž d S r   )Ú__dict__r   r9   r?   r@   )r   Ústater
   r
   r   Ú__setstate__Ù  s   "zConnectionPool.__setstate__)%r   r   r   r	   ÚsplitrA   r    rC   rD   r'   rq   r   r   rR   r   r^   r*   rt   rU   r   rK   rO   r\   rX   rc   rg   ri   r   rT   r#   r   rm   ra   re   rh   ry   r|   r
   r
   r
   r   r.   ~   s@    G%r.   N)r	   r=   r   rF   r   r   rs   r   r   r*   r.   Ú__all__r
   r
   r
   r   Ú<module>   s   71  b