o
    JhK                     @   s  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 d dlmZ d d	lZd d	lZd d	l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 edZG dd dZG dd deZG dd dZdd Z dd Z!d	S )    )abc)datetime)timezone)contextmanagerimport_module)count)	getLogger)entry_pointsN)
exceptions)internalmigrations)utils)topological_sortzyoyo.migrationsc                   @   sB   e Zd ZdZdddZdd Zdd Zd	d
 Zdd Zdd Z	dS )TransactionManagerz
    Returned by the :meth:`~yoyo.backends.DatabaseBackend.transaction`
    context manager.

    If rollback is called, the transaction is flagged to be rolled back
    when the context manager block closes
    Fc                 C   s   || _ || _d S N)backendrollback_on_exit)selfr   r    r   T/var/www/html/pro-man-master/venv/lib/python3.10/site-packages/yoyo/backends/base.py__init__1   s   
zTransactionManager.__init__c                 C   s   |    | S r   )	_do_beginr   r   r   r   	__enter__5   s   zTransactionManager.__enter__c                 C   s.   |r|    d S | jr|    d S |   d S r   )_do_rollbackr   
_do_commit)r   exc_typevalue	tracebackr   r   r   __exit__9   s   zTransactionManager.__exit__c                 C      | j   dS )z=
        Instruct the backend to begin a transaction
        N)r   beginr   r   r   r   r   C      zTransactionManager._do_beginc                 C   r    )z@
        Instruct the backend to commit the transaction
        N)r   commitr   r   r   r   r   I   r"   zTransactionManager._do_commitc                 C   r    )zC
        Instruct the backend to roll back the transaction
        N)r   rollbackr   r   r   r   r   O   r"   zTransactionManager._do_rollbackNF)
__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r   r   r   (   s    

r   c                   @   s0   e Zd ZdZedZdd Zdd Zdd ZdS )	SavepointTransactionManagerN   c                 C   s2   | j d u sJ dt| j| _ | j| j  d S )Nzsp_{})idformatnextid_generatorr   	savepointr   r   r   r   r   Z   s   z%SavepointTransactionManager._do_beginc                 C      dS )z
        This does nothing.

        Trying to the release savepoint here could cause an database error in
        databases where DDL queries cause the transaction to be committed
        and all savepoints released.
        Nr   r   r   r   r   r   _       z&SavepointTransactionManager._do_commitc                 C   s   | j | j d S r   )r   savepoint_rollbackr,   r   r   r   r   r   h   s   z(SavepointTransactionManager._do_rollback)	r&   r'   r(   r,   r   r/   r   r   r   r   r   r   r   r*   V   s    	r*   c                   @   s.  e Zd ZU dZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZi Zeeef ed< dd Zdd Zdd Zdd Zedd Ze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-e(e) fd.d/Z*dud0d1Z+d2d3 Z,d4d5 Z-d6d7 Z.d8d9 Z/d:d; Z0d<d= Z1d>d? Z2e3d@dA Z4e3dvdCdDZ5dwdFdGZ6dHdI Z7dJdK Z8dxdLe9j:e;j<e)e9j=f df fdMdNZ>dOdP Z?dQdR Z@dSdT ZAdUdV ZBdWdX ZCdYdZ ZDdud[d\ZEdud]d^ZFdud_d`ZGdudadbZHdcdd ZIdedf ZJdydhdiZKdudjdkZLdzdldmZMdzdndoZNdpdq ZOd{dsdtZPdS )|DatabaseBackend 	_yoyo_log	yoyo_lockz0SELECT table_name FROM information_schema.tables_yoyo_version_yoyo_migrationszW
        SELECT COUNT(1) FROM {0.migration_table_quoted}
        WHERE {quoted.id}=:id}zINSERT INTO {0.migration_table_quoted} ({quoted.migration_hash}, {quoted.migration_id}, {quoted.applied_at_utc}) VALUES (:migration_hash, :migration_id, :when)zVDELETE FROM {0.migration_table_quoted} WHERE {quoted.migration_hash} = :migration_hashz_SELECT {quoted.migration_hash} FROM {0.migration_table_quoted} ORDER by {quoted.applied_at_utc}z>CREATE TABLE {table_name_quoted} ({quoted.id} INT PRIMARY KEY)a  INSERT INTO {0.log_table_quoted} ({quoted.id}, {quoted.migration_hash}, {quoted.migration_id}, {quoted.operation}, {quoted.username}, {quoted.hostname}, {quoted.created_at_utc}) VALUES (:id, :migration_hash, :migration_id, :operation, :username, :hostname, :created_at_utc)zCREATE TABLE {0.lock_table_quoted} ({quoted.locked} INT DEFAULT 1, {quoted.ctime} TIMESTAMP,{quoted.pid} INT NOT NULL,PRIMARY KEY ({quoted.locked}))NF_transactional_ddl_cachec                 C   sJ   || _ | jj| _| || _| | j || _| jt	
| j d| _d S )NT)uridriverDatabaseErrorconnect_connectioninit_connectionmigration_tabler:   getpickledumpshas_transactional_ddl)r   dburirA   r   r   r   r      s   

zDatabaseBackend.__init__c                 C   s*   |    |  | _| j| jt| j< d S r   )create_lock_table_check_transactional_ddlrE   r:   rC   rD   r;   r   r   r   r   init_database   s   

zDatabaseBackend.init_databasec                 C   s   t | j}t|j |S )zT
        Load the dbapi driver module and register the base exception class
        )get_dbapi_moduledriver_moduler   registerr=   )r   r<   r   r   r   _load_driver_module   s   
z#DatabaseBackend._load_driver_modulec                    s0   | j  G  fddd}|j| fd| i|S )zt
        Take a string in the format used by the various ``..._sql`` class
        variables and format it.
        c                       s   e Zd Z fddZdS )z*DatabaseBackend.format_sql.<locals>.Quoterc                    s    |S r   r   )r   squote_identifierr   r   __getattr__   s   z6DatabaseBackend.format_sql.<locals>.Quoter.__getattr__N)r&   r'   r(   rQ   r   rO   r   r   Quoter   s    rR   quoted)rP   r-   )r   rN   kwargsrR   r   rO   r   
format_sql   s   zDatabaseBackend.format_sqlc                 C   s   | j r| j S |  | _ | j S r   )_driverrM   r   r   r   r   r<      s   
zDatabaseBackend.driverc                 C   s   | j S r   )r?   r   r   r   r   
connection   s   zDatabaseBackend.connectionc                 C   r1   )z
        Called when creating a connection or after a rollback. May do any
        db specific tasks required to make the connection ready for use.
        Nr   )r   rW   r   r   r   r@      r2   zDatabaseBackend.init_connectionc                 C   s   |  | j| jS )zX
        Return a copy of the backend with a independent db
        connection.
        )	__class__r;   rA   r   r   r   r   copy   s   zDatabaseBackend.copyc                 C   s   | S r   r   r   r   r   r   r      s   zDatabaseBackend.__enter__c                 C   s   | j   d S r   )rW   close)r   r   	exc_valuer   r   r   r   r         zDatabaseBackend.__exit__c                 C   s0   | drt| |dd }| |S t|)N_quotedr   )endswithgetattrrsplitrP   AttributeError)r   attrnameunquotedr   r   r   rQ      s   

zDatabaseBackend.__getattr__c                 C   s   t  r   )NotImplementedError)r   rF   r   r   r   r>      s   zDatabaseBackend.connectc                 C   s$   d|vsJ | dd}d| dS )N "z"")replace)r   rN   rS   r   r   r   rP      s   z DatabaseBackend.quote_identifierc                 C   s   d td}| |}| j| j|d}z| jdd | | W d   n1 s,w   Y  W n | jy=   Y dS w z!|   | d|  W d   W dS 1 sXw   Y  W dS  | jyj   Y dS w )	zz
        Return True if the database supports committing/rolling back
        DDL statements within a transaction
        zyoyo_tmp_{}
   )table_name_quotedTr   NFzDROP TABLE )	r-   r   get_random_stringrP   rU   create_test_table_sqltransactionexecuter=   )r   
table_nameri   sqlr   r   r   rH      s.   

z(DatabaseBackend._check_transactional_ddlreturnc                 K   s4   |  | jtd| jjifi |}dd | D S )z
        Return a list of tables present in the backend.
        This is used by the test suite to clean up tables
        generated during testing
        databasec                 S      g | ]}|d  qS r   r   .0rowr   r   r   
<listcomp>      z/DatabaseBackend.list_tables.<locals>.<listcomp>)rn   list_tables_sqldictr;   rr   fetchall)r   rT   cursorr   r   r   list_tables	  s
   zDatabaseBackend.list_tablesc                 C   s   | j s	t| |dS t| |dS )Nrj   )_in_transactionr   r*   )r   r   r   r   r   rm     s   zDatabaseBackend.transactionc                 C   s
   | j  S r   )rW   r}   r   r   r   r   r}     s   
zDatabaseBackend.cursorc                 C   s   | j   d| _d S NF)rW   r#   r   r   r   r   r   r#     s   

zDatabaseBackend.commitc                 C   s    | j   | | j  d| _d S r   )rW   r$   r@   r   r   r   r   r   r$   #  s   

zDatabaseBackend.rollbackc                 C   s   | j rJ d| _ | d dS )z)
        Begin a new transaction
        TBEGINN)r   rn   r   r   r   r   r!   (  s   
zDatabaseBackend.beginc                 C      |  d| |  dS )z:
        Create a new savepoint with the given id
        z
SAVEPOINT Nrn   rP   r   r,   r   r   r   r0   0     zDatabaseBackend.savepointc                 C   r   )zB
        Release (commit) the savepoint with the given id
        zRELEASE SAVEPOINT Nr   r   r   r   r   savepoint_release6  r   z!DatabaseBackend.savepoint_releasec                 C   r   )z:
        Rollback the savepoint with the given id
        zROLLBACK TO SAVEPOINT Nr   r   r   r   r   r3   <  r   z"DatabaseBackend.savepoint_rollbackc                 c   s    |    dV  dS )z
        Disable the connection's transaction support, for example by
        setting the isolation mode to 'autocommit'
        N)r$   r   r   r   r   disable_transactionsB  s   
z$DatabaseBackend.disable_transactionsrh   c              	   c   sV    | j r	dV  dS t }| || zd| _ dV  d| _ W | | dS | | w )z
        Create a lock to prevent concurrent migrations.

        :param timeout: duration in seconds before raising a LockTimeout error.
        NTF)
_is_lockedosgetpid_insert_lock_row_delete_lock_row)r   timeoutpidr   r   r   lockK  s   zDatabaseBackend.lock      ?c                 C   s  t ||}t }| j}	 z>|  / | d| j d|d d|d d|d d	ttj	j
d d	|d
 W d    W d S 1 sDw   Y  W d S  | jy   |rt || kr| d|d d| j }| }|r|td|d  dtdt| Y nw q)NTz%
                        INSERT INTO z
                        (lockedz, ctimer   zJ)
                        VALUES (1, :when, :pid)
                        tzinfo)whenr   zSELECT z FROM zProcess r   zC has locked this database (run yoyo break-lock to remove this lock)z9Database locked (run yoyo break-lock to remove this lock))mintimerP   rm   rn   lock_table_quotedr   nowr   utcrg   r=   fetchoner   LockTimeoutsleep)r   r   r   poll_intervalstartedqir}   rw   r   r   r   r   _  sP   

z DatabaseBackend._insert_lock_rowc                 C   sX   |    | j}| d| j d|d dd|i W d    d S 1 s%w   Y  d S )NDELETE FROM z WHERE r   z=:pid)rm   rP   rn   r   )r   r   r   r   r   r   r     s   
"z DatabaseBackend._delete_lock_rowc                 C   s@   |    | d| j  W d    d S 1 sw   Y  d S )Nr   )rm   rn   r   r   r   r   r   
break_lock  s   
"zDatabaseBackend.break_lockparamsc                 C   s.   |   }t| jj||\}}||| |S )a'  
        Create a new cursor, execute a single statement and return the cursor
        object.

        :param sql: A single SQL statement, optionally with named parameters
                    (eg 'SELECT * FROM foo WHERE :bar IS NULL')
        :param params: A dictionary of parameters
        )r}   r   change_param_styler<   
paramstylern   )r   rp   r   r}   queryparamsr   r   r   rn     s   	zDatabaseBackend.executec                 C   s\   z"|    | | | j W d   W dS 1 sw   Y  W dS  | jy-   Y dS w )zE
        Create the lock table if it does not already exist.
        N)rm   rn   rU   create_lock_table_sqlr=   r   r   r   r   rG     s   
&z!DatabaseBackend.create_lock_tablec                 C   sj   | j rdS t| r3| jrJ |   t|  | j  d| _ W d   dS 1 s,w   Y  dS dS )z;
        Check and upgrade yoyo's internal schema.
        NT)_internal_schema_updatedr   needs_upgradingr   r   upgraderW   r#   r   r   r   r   ensure_internal_schema_updated  s   




"z.DatabaseBackend.ensure_internal_schema_updatedc                 C   s   |j |  v S r   )hashget_applied_migration_hashes)r   	migrationr   r   r   
is_applied  r\   zDatabaseBackend.is_appliedc                 C   s,   |    | | j}dd | | D S )ze
        Return the list of migration hashes in the order in which they
        were applied
        c                 S   rs   rt   r   ru   r   r   r   rx     ry   z@DatabaseBackend.get_applied_migration_hashes.<locals>.<listcomp>)r   rU   applied_migrations_sqlrn   r|   )r   rp   r   r   r   r     s   z,DatabaseBackend.get_applied_migration_hashesc                    s,   |     fdd|D }|t||jS )zF
        Return the subset of migrations not already applied.
        c                 3   s    | ]
}|j  vr|V  qd S r   r   rv   mappliedr   r   	<genexpr>      z+DatabaseBackend.to_apply.<locals>.<genexpr>)r   rX   r   
post_applyr   
migrationsmsr   r   r   to_apply  s   zDatabaseBackend.to_applyc                    s4   |     fdd|D }|ttt||jS )z
        Return the subset of migrations already applied and which may be
        rolled back.

        The order of migrations will be reversed.
        c                 3   s    | ]
}|j  v r|V  qd S r   r   r   r   r   r   r     r   z.DatabaseBackend.to_rollback.<locals>.<genexpr>)r   rX   reversedlistr   r   r   r   r   r   to_rollback  s
   zDatabaseBackend.to_rollbackc                 C   s(   |r| j ||d | j||d d S d S )Nforce)apply_migrations_onlyrun_post_apply)r   r   r   r   r   r   apply_migrations  s   z DatabaseBackend.apply_migrationsc              	   C   s<   |sdS |D ]}z	| j ||d W q tjy   Y qw dS )zd
        Apply the list of migrations, but do not run any post-apply hooks
        present.
        Nr   )	apply_oner   BadMigrationr   r   r   r   r   r   r   r     s   z%DatabaseBackend.apply_migrations_onlyc                 C   s    |j D ]
}| j|d|d qdS )zI
        Run any post-apply migrations present in ``migrations``
        F)markr   N)r   r   r   r   r   r   r     s   
zDatabaseBackend.run_post_applyc              	   C   sB   |    |sd S |D ]}z| || W q
 tjy   Y q
w d S r   )r   rollback_oner   r   r   r   r   r   rollback_migrations  s   z#DatabaseBackend.rollback_migrationsc              
   C   b   |    |   |D ]}z| | W q tjy   Y qw W d    d S 1 s*w   Y  d S r   )r   rm   mark_oner   r   r   r   r   r   r   r   mark_migrations     
"zDatabaseBackend.mark_migrationsc              
   C   r   r   )r   rm   
unmark_oner   r   r   r   r   r   unmark_migrations  r   z!DatabaseBackend.unmark_migrationsTc                 C   s   t d|j |   |  }|j|d|d W d   n1 s"w   Y  | |d |rM|   | j|dd W d   dS 1 sFw   Y  dS dS )z*
        Apply a single migration
        zApplying %sapplyr   NFlog)	loggerinfor,   r   rY   process_stepslog_migrationrm   r   )r   r   r   r   migration_backendr   r   r   r     s   

"zDatabaseBackend.apply_onec                 C   s   t d|j |   |  }|j|d|d W d   n1 s"w   Y  | |d |   | j|dd W d   dS 1 sDw   Y  dS )z-
        Rollback a single migration
        zRolling back %sr$   r   NFr   )	r   r   r,   r   rY   r   r   rm   r   )r   r   r   r   r   r   r   r     s   

"zDatabaseBackend.rollback_onec                 C   s>   |    | | j}| |d|ji |r| |d d S d S )Nmigration_hashunmark)r   rU   unmark_migration_sqlrn   r   r   r   r   r   rp   r   r   r   r   $  s   zDatabaseBackend.unmark_onec                 C   sb   |    td|j | | j}| ||j|jt	t
jjd dd |r/| |d d S d S )NzMarking %s appliedr   )r   migration_idr   r   )r   r   r   r,   rU   mark_migration_sqlrn   r   r   r   r   r   rg   r   r   r   r   r   r   +  s   zDatabaseBackend.mark_onec                 C   s$   |  | j}| || || d S r   )rU   log_migration_sqlrn   get_log_data)r   r   	operationrp   r   r   r   r   :  s   zDatabaseBackend.log_migrationr   c                 C   sT   |dv sJ t t |r|jnd|r|jndt t t	
tjjdd|dS )zR
        Return a dict of data for insertion into the ``_yoyo_log`` table
        >   r   r   r   r$   Nr   )r,   r   r   usernamehostnamecreated_at_utcr   )struuiduuid1r,   r   getpassgetusersocketgetfqdnr   r   r   r   rg   )r   r   r   r   r   r   r   >  s   
zDatabaseBackend.get_log_datar%   )rh   )r   r   )FT)T)Nr   )Qr&   r'   r(   rK   	log_table
lock_tablerz   version_tablerA   is_applied_sqlr   r   r   rl   r   r   rV   r   r   r   r:   r{   bytesbool__annotations__r   rI   rM   rU   propertyr<   rW   r@   rY   r   r   rQ   r>   rP   rH   r   r   r~   rm   r}   r#   r$   r!   r0   r   r3   r   r   r   r   r   r   tUnionr   MappingAnyrn   rG   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r4   l   s   
 	





%&
	




	
	


r4   c                 C   s   t dd}||   S )Nzyoyo.backends)group)r
   load)namebackend_epsr   r   r   get_backend_classN  s   
r   c                 C   s   t | S )z:
    Import and return the named DB-API driver module
    r   )r   r   r   r   rJ   S  s   rJ   )"collectionsr   r   r   
contextlibr   	importlibr   	itertoolsr   loggingr	   importlib_metadatar
   r   r   rC   r   r   typingr   r   yoyor   r   r   yoyo.migrationsr   r   r   r*   r4   r   rJ   r   r   r   r   <module>   s8   .   e