U
    nËj�  ã                
   @   sÆ   d dl Z d dlmZ d dlmZmZmZ d dlmZm	Z	m
Z
 zHd dlmZmZmZmZmZmZmZmZmZ d dlmZ d dlmZ W n, ek
r° Z zedƒe‚W 5 dZ[X Y nX G d	d
„ d
eƒZdS )é    N)ÚJob)ÚBaseJobStoreÚConflictingIdErrorÚJobLookupError)Údatetime_to_utc_timestampÚ	maybe_refÚutc_timestamp_to_datetime)	ÚColumnÚFloatÚLargeBinaryÚMetaDataÚTableÚUnicodeÚand_Úcreate_engineÚselect)ÚIntegrityError)Únullz0SQLAlchemyJobStore requires SQLAlchemy installedc                       sž   e Zd ZdZddddejddf‡ fdd„	Z‡ f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‡  ZS ) ÚSQLAlchemyJobStorea¸  
    Stores jobs in a database table using SQLAlchemy.
    The table will be created if it doesn't exist in the database.

    Plugin alias: ``sqlalchemy``

    :param str url: connection string (see
        :ref:`SQLAlchemy documentation <sqlalchemy:database_urls>` on this)
    :param engine: an SQLAlchemy :class:`~sqlalchemy.engine.Engine` to use instead of creating a
        new one based on ``url``
    :param str tablename: name of the table to store jobs in
    :param metadata: a :class:`~sqlalchemy.schema.MetaData` instance to use instead of creating a
        new one
    :param int pickle_protocol: pickle protocol level to use (for serialization), defaults to the
        highest available
    :param str tableschema: name of the (existing) schema in the target database where the table
        should be
    :param dict engine_options: keyword arguments to :func:`~sqlalchemy.create_engine`
        (ignored if ``engine`` is given)
    NZapscheduler_jobsc              
      sŽ   t ƒ  ¡  || _t|ƒptƒ }|r.t|ƒ| _n |rFt|f|p>i Ž| _ntdƒ‚t||t	dt
dƒdd�t	dtdƒdd�t	d	td
d�|d�| _d S )Nz%Need either "engine" or "url" definedÚidé¿   T)Zprimary_keyÚnext_run_timeé   )ÚindexÚ	job_stateF)Znullable)Zschema)ÚsuperÚ__init__Úpickle_protocolr   r   Úenginer   Ú
ValueErrorr   r	   r   r
   r   Újobs_t)ÚselfÚurlr   Z	tablenameÚmetadatar   ZtableschemaZengine_options©Ú	__class__© úD/tmp/pip-unpacked-wheel-giblih11/apscheduler/jobstores/sqlalchemy.pyr   3   s     

úzSQLAlchemyJobStore.__init__c                    s"   t ƒ  ||¡ | j | jd¡ d S )NT)r   Ústartr    Úcreater   )r!   Z	schedulerÚaliasr$   r&   r'   r(   S   s    zSQLAlchemyJobStore.startc              
   C   s`   t | jjjƒ | jjj|k¡}| j ¡ �.}| |¡ 	¡ }|rF|  
|¡nd W  5 Q R £ S Q R X d S ©N)r   r    Úcr   Úwherer   r   ÚbeginÚexecuteÚscalarÚ_reconstitute_job)r!   Újob_idÚ
selectableÚ
connectionr   r&   r&   r'   Ú
lookup_jobW   s    zSQLAlchemyJobStore.lookup_jobc                 C   s   t |ƒ}|  | jjj|k¡S r+   )r   Ú	_get_jobsr    r,   r   )r!   ÚnowÚ	timestampr&   r&   r'   Úget_due_jobs]   s    zSQLAlchemyJobStore.get_due_jobsc              
   C   sj   t | jjjƒ | jjjtƒ k¡ | jjj¡ d¡}| j 	¡ �$}| 
|¡ ¡ }t|ƒW  5 Q R £ S Q R X d S )Né   )r   r    r,   r   r-   r   Úorder_byÚlimitr   r.   r/   r0   r   )r!   r3   r4   r   r&   r&   r'   Úget_next_run_timea   s    ÿþýÿz$SQLAlchemyJobStore.get_next_run_timec                 C   s   |   ¡ }|  |¡ |S r+   )r6   Z_fix_paused_jobs_sorting)r!   Újobsr&   r&   r'   Úget_all_jobsl   s    
zSQLAlchemyJobStore.get_all_jobsc              	   C   sx   | j  ¡ jf |jt|jƒt | ¡ | j	¡dœŽ}| j
 ¡ �4}z| |¡ W n tk
rh   t|jƒ‚Y nX W 5 Q R X d S )N)r   r   r   )r    ÚinsertÚvaluesr   r   r   ÚpickleÚdumpsÚ__getstate__r   r   r.   r/   r   r   )r!   Újobr@   r4   r&   r&   r'   Úadd_jobq   s    ýÿzSQLAlchemyJobStore.add_jobc              	   C   sv   | j  ¡ jf t|jƒt | ¡ | j¡dœŽ 	| j j
j|jk¡}| j ¡ �$}| |¡}|jdkrht|jƒ‚W 5 Q R X d S )N)r   r   r   )r    ÚupdaterA   r   r   rB   rC   rD   r   r-   r,   r   r   r.   r/   Úrowcountr   )r!   rE   rG   r4   Úresultr&   r&   r'   Ú
update_job   s    þþùÿ


zSQLAlchemyJobStore.update_jobc              	   C   sP   | j  ¡  | j jj|k¡}| j ¡ �"}| |¡}|jdkrBt	|ƒ‚W 5 Q R X d S )Nr   )
r    Údeleter-   r,   r   r   r.   r/   rH   r   )r!   r2   rK   r4   rI   r&   r&   r'   Ú
remove_job�   s
    

zSQLAlchemyJobStore.remove_jobc              	   C   s.   | j  ¡ }| j ¡ �}| |¡ W 5 Q R X d S r+   )r    rK   r   r.   r/   )r!   rK   r4   r&   r&   r'   Úremove_all_jobs–   s    
z"SQLAlchemyJobStore.remove_all_jobsc                 C   s   | j  ¡  d S r+   )r   Zdispose©r!   r&   r&   r'   Úshutdown›   s    zSQLAlchemyJobStore.shutdownc                 C   s:   t  |¡}| |d< t t¡}| |¡ | j|_| j|_|S )NZjobstore)rB   Úloadsr   Ú__new__Ú__setstate__Z
_schedulerÚ_aliasZ_jobstore_alias)r!   r   rE   r&   r&   r'   r1   ž   s    


z$SQLAlchemyJobStore._reconstitute_jobc              
   G   sÞ   g }t | jjj| jjjƒ | jjj¡}|r8| t|Ž ¡n|}t	ƒ }| j
 ¡ �ˆ}| |¡D ]L}z| |  |j¡¡ W qX tk
r¢   | j d|j¡ | |j¡ Y qXX qX|rÐ| j ¡  | jjj |¡¡}| |¡ W 5 Q R X |S )Nz)Unable to restore job "%s" -- removing it)r   r    r,   r   r   r;   r   r-   r   Úsetr   r.   r/   Úappendr1   ÚBaseExceptionZ_loggerÚ	exceptionÚaddrK   Zin_)r!   Z
conditionsr>   r3   Zfailed_job_idsr4   ÚrowrK   r&   r&   r'   r6   §   s,    ÿ ÿ
ÿzSQLAlchemyJobStore._get_jobsc                 C   s   d| j j› d| jj› d�S )Nú<z (url=z)>)r%   Ú__name__r   r"   rN   r&   r&   r'   Ú__repr__Á   s    zSQLAlchemyJobStore.__repr__)r[   Ú
__module__Ú__qualname__Ú__doc__rB   ÚHIGHEST_PROTOCOLr   r(   r5   r9   r=   r?   rF   rJ   rL   rM   rO   r1   r6   r\   Ú__classcell__r&   r&   r$   r'   r      s,   ø 	r   )rB   Zapscheduler.jobr   Zapscheduler.jobstores.baser   r   r   Zapscheduler.utilr   r   r   Z
sqlalchemyr	   r
   r   r   r   r   r   r   r   Zsqlalchemy.excr   Zsqlalchemy.sql.expressionr   ÚImportErrorÚexcr   r&   r&   r&   r'   Ú<module>   s   ,