a
    g	gNP                  
   @  s  d dl m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	 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 ervd 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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#d$d%d&d'Z*d"d#d(d%d)d*Z+d@d/d0d0d1d2d3d4d0d5d6d7Z,d"d8d3d9d:d;Z-G d<d= d=Z.G d>d? d?Z/dS )A    )annotationsN)Any)Callable)Dict)Iterator)Optional)Set)Tuple)TYPE_CHECKING)Union)inspect   )compare)render   )util)ops)
Connection)Dialect)	Inspector)Column)ForeignKeyConstraint)Index)MetaData)Table)UniqueConstraint)Config)MigrationScript)
UpgradeOpsMigrationContext)Script)ScriptDirectoryr    r   r   )contextmetadatareturnc                 C  s   t | |}|j S )a
  Compare a database schema to that given in a
    :class:`~sqlalchemy.schema.MetaData` instance.

    The database connection is presented in the context
    of a :class:`.MigrationContext` object, which
    provides database connectivity as well as optional
    comparison functions to use for datatypes and
    server defaults - see the "autogenerate" arguments
    at :meth:`.EnvironmentContext.configure`
    for details on these.

    The return format is a list of "diff" directives,
    each representing individual differences::

        from alembic.migration import MigrationContext
        from alembic.autogenerate import compare_metadata
        from sqlalchemy.schema import SchemaItem
        from sqlalchemy.types import TypeEngine
        from sqlalchemy import (create_engine, MetaData, Column,
                Integer, String, Table, text)
        import pprint

        engine = create_engine("sqlite://")

        with engine.begin() as conn:
            conn.execute(text('''
                create table foo (
                    id integer not null primary key,
                    old_data varchar,
                    x integer
                )'''))

            conn.execute(text('''
                create table bar (
                    data varchar
                )'''))

        metadata = MetaData()
        Table('foo', metadata,
            Column('id', Integer, primary_key=True),
            Column('data', Integer),
            Column('x', Integer, nullable=False)
        )
        Table('bat', metadata,
            Column('info', String)
        )

        mc = MigrationContext.configure(engine.connect())

        diff = compare_metadata(mc, metadata)
        pprint.pprint(diff, indent=2, width=20)

    Output::

        [ ( 'add_table',
            Table('bat', MetaData(bind=None),
                Column('info', String(), table=<bat>), schema=None)),
          ( 'remove_table',
            Table(u'bar', MetaData(bind=None),
                Column(u'data', VARCHAR(), table=<bar>), schema=None)),
          ( 'add_column',
            None,
            'foo',
            Column('data', Integer(), table=<foo>)),
          ( 'remove_column',
            None,
            'foo',
            Column(u'old_data', VARCHAR(), table=None)),
          [ ( 'modify_nullable',
              None,
              'foo',
              u'x',
              { 'existing_server_default': None,
                'existing_type': INTEGER()},
              True,
              False)]]


    :param context: a :class:`.MigrationContext`
     instance.
    :param metadata: a :class:`~sqlalchemy.schema.MetaData`
     instance.

    .. seealso::

        :func:`.produce_migrations` - produces a :class:`.MigrationScript`
        structure based on metadata comparison.

    )produce_migrationsupgrade_opsZas_diffs)r#   r$   migration_script r)   [/var/www/html/llm_bihealth/app/venv/lib/python3.9/site-packages/alembic/autogenerate/api.pycompare_metadata+   s    [
r+   r   c                 C  s8   t | |d}tjdtg tg d}t|| |S )a  Produce a :class:`.MigrationScript` structure based on schema
    comparison.

    This function does essentially what :func:`.compare_metadata` does,
    but then runs the resulting list of diffs to produce the full
    :class:`.MigrationScript` object.   For an example of what this looks like,
    see the example in :ref:`customizing_revision`.

    .. seealso::

        :func:`.compare_metadata` - returns more fundamental "diff"
        data from comparing a schema.

    )r$   Nrev_idr'   downgrade_ops)AutogenContextr   r   r   DowngradeOpsr   _populate_migration_script)r#   r$   autogen_contextr(   r)   r)   r*   r&      s    r&   sa.op.Fr)   r   strboolzTuple[str, ...]NonezOptional[MigrationContext])up_or_down_opsqlalchemy_module_prefixalembic_module_prefixrender_as_batchimportsrender_itemmigration_contextr%   c                 C  sd   ||||d}|du r<ddl m} ddlm}	 |j|	 d}t||d}
t||
_t	t
| |
S )	zRender Python code given an :class:`.UpgradeOps` or
    :class:`.DowngradeOps` object.

    This is a convenience function that can be used to test the
    autogenerate output of a user-defined :class:`.MigrationScript` structure.

    )r9   r:   r=   r;   Nr   r   r   )DefaultDialect)dialect)opts)Zruntime.migrationr    Zsqlalchemy.engine.defaultr?   	configurer/   setr<   r   _indentZ_render_cmd_body)r8   r9   r:   r;   r<   r=   r>   rA   r    r?   r2   r)   r)   r*   render_python_code   s     

rE   zDict[Any, Any])r#   template_argsr%   c                 C  sD   t | }tg }t|| tjd|| d}t||| dS )z6legacy, used by test_autogen_composition at the momentNr,   )	r/   r   r   r   Z_produce_net_changesr   reverser    _render_python_into_templatevars)r#   rF   r2   r'   r(   r)   r)   r*   _render_migration_diffs   s    
rI   c                   @  s   e Zd ZU dZdZded< dZded< dZded< dZd	ed
< dZ	ded< d*ddddddddZ
ejddddZejddddZddddddd Zd!dddd"dd#d$d%ZeZejd&d' Zejd(d) ZdS )+r/   zSMaintains configuration and state that's specific to an
    autogenerate operation.NzOptional[MetaData]r$   zOptional[Connection]
connectionzOptional[Dialect]r@   zSet[str]r<   r    r>   TzOptional[dict]r6   r7   )r>   r$   rA   autogenerater%   c           	      C  s   |r|d ur|j rtd|d u r*|j}|d u r>|dd n| | _}|rx|d u rx|d urx|jd urxtd|jj |dd }|dd }g }g }|r|| |r|| || _	|| _
|| _| jd ur| jj| _| jj| _t | _|| _d| _d S )Nz^autogenerate can't use as_sql=True as it prevents querying the database for schema informationZtarget_metadatazCan't proceed with --autogenerate option; environment script %s does not provide a MetaData object or sequence of objects to the context.include_objectinclude_nameF)Zas_sqlr   CommandErrorrA   getr$   scriptZenv_py_locationappend_object_filters_name_filtersr>   bindrJ   r@   rC   r<   
_has_batch)	selfr>   r$   rA   rK   rL   rM   Zobject_filtersZname_filtersr)   r)   r*   __init__  sV    	




zAutogenContext.__init__r   r%   c                 C  s   | j d u rtdt| j S )NzHcan't return inspector as this AutogenContext has no database connection)rJ   	TypeErrorr   rV   r)   r)   r*   	inspectorX  s
    
zAutogenContext.inspectorzIterator[None]c                 c  s   d| _ d V  d| _ d S )NTF)rU   rZ   r)   r)   r*   _within_batcha  s    zAutogenContext._within_batchzOptional[str]r5   zDict[str, Optional[str]])nametype_parent_namesr%   c                 C  sn   d|v rL|dkr|}n| dd}|rL|d }|rDd||f |d< n||d< | jD ]}||||sR dS qRdS )	a  Run the context's name filters and return True if the targets
        should be part of the autogenerate operation.

        This method should be run for every kind of name encountered within the
        reflection side of an autogenerate operation, giving the environment
        the chance to filter what names should be reflected as database
        objects.  The filters here are produced directly via the
        :paramref:`.EnvironmentContext.configure.include_name` parameter.

        schema_nametable
table_nameNz%s.%sZschema_qualified_table_nameFT)rO   rS   )rV   r]   r^   r_   rb   r`   fnr)   r)   r*   run_name_filtersg  s     
zAutogenContext.run_name_filterszCUnion[Table, Index, Column, UniqueConstraint, ForeignKeyConstraint]z7Optional[Union[Table, Index, Column, UniqueConstraint]])object_r]   r^   	reflected
compare_tor%   c                 C  s&   | j D ]}||||||s dS qdS )a  Run the context's object filters and return True if the targets
        should be part of the autogenerate operation.

        This method should be run for every kind of object encountered within
        an autogenerate operation, giving the environment the chance
        to filter what objects should be included in the comparison.
        The filters here are produced directly via the
        :paramref:`.EnvironmentContext.configure.include_object` parameter.

        FTN)rR   )rV   re   r]   r^   rf   rg   rc   r)   r)   r*   run_object_filters  s    
z!AutogenContext.run_object_filtersc                 C  s&   g }t | jD ]}||j q|S )ai  Return an aggregate of the :attr:`.MetaData.sorted_tables`
        collection(s).

        For a sequence of :class:`.MetaData` objects, this
        concatenates the :attr:`.MetaData.sorted_tables` collection
        for each individual :class:`.MetaData`  in the order of the
        sequence.  It does **not** collate the sorted tables collections.

        )r   to_listr$   extendsorted_tables)rV   resultmr)   r)   r*   rk     s    zAutogenContext.sorted_tablesc                 C  s^   i }t | jD ]H}t|t|j}|rLtdddd t|D  |	|j q|S )a  Return an aggregate  of the :attr:`.MetaData.tables` dictionaries.

        The :attr:`.MetaData.tables` collection is a dictionary of table key
        to :class:`.Table`; this method aggregates the dictionary across
        multiple :class:`.MetaData` objects into one dictionary.

        Duplicate table keys are **not** supported; if two :class:`.MetaData`
        objects contain the same table key, an exception is raised.

        z9Duplicate table keys across multiple MetaData objects: %sz, c                 s  s   | ]}d | V  qdS )z"%s"Nr)   ).0keyr)   r)   r*   	<genexpr>      z4AutogenContext.table_key_to_table.<locals>.<genexpr>)
r   ri   r$   rC   intersectionZtables
ValueErrorjoinsortedupdate)rV   rl   rm   Z	intersectr)   r)   r*   table_key_to_table  s    z!AutogenContext.table_key_to_table)NNT)__name__
__module____qualname____doc__r$   __annotations__rJ   r@   r<   r>   rW   r   Zmemoized_propertyr[   
contextlibcontextmanagerr\   rd   rh   Zrun_filtersrk   rw   r)   r)   r)   r*   r/      s*   
	   <&
r/   c                   @  s   e Zd ZdZd!ddddddd	d
ZdddddZddddddZddddddZdddddddZddddZ	dddd Z
dS )"RevisionContextz^Maintains configuration and state that's specific to a revision
    file generation operation.Nr   r"   zDict[str, Any]zOptional[Callable]r7   )configscript_directorycommand_argsprocess_revision_directivesr%   c                 C  s2   || _ || _|| _|| _d|i| _|  g| _d S )Nr   )r   r   r   r   rF   _default_revisiongenerated_revisions)rV   r   r   r   r   r)   r)   r*   rW     s    zRevisionContext.__init__r   zOptional[Script])r(   r%   c              	   C  s   | j  }t|ddrF| j}t |_|jr8|j|j t||| |j	d usTJ | j
j|j	|jfd|j|j|j|j|jd|S )N_needs_renderFT)ZrefreshheadspliceZbranch_labelsversion_path
depends_on)rF   copygetattr_last_autogen_contextrC   r<   rv   r   rH   r-   r   Zgenerate_revisionmessager   r   branch_labelr   r   )rV   r(   rF   r2   r)   r)   r*   
_to_script  s.    
	zRevisionContext._to_scripttupler    )revr>   r%   c                 C  s   |  ||d d S )NT_run_environmentrV   r   r>   r)   r)   r*   run_autogenerate
  s    z RevisionContext.run_autogeneratec                 C  s   |  ||d d S )NFr   r   r)   r)   r*   run_no_autogenerate  s    z#RevisionContext.run_no_autogenerater6   )r   r>   rK   r%   c           	      C  s&  |rB| j d rtdt| j|t| jdkrBtd|jd }|jd }| jd }t|dd	s||j	d _
||jd _d
|_n,|jtjg |d |jtjg |d t||d}|| _|rt|| | jr| ||| j |jd }|r|||| j | jD ]}d
|_qd S )NZsqlz7Using --sql with --autogenerate does not make any senseZheadsz"Target database is not up to date.upgrade_tokendowngrade_tokenr   FT)r   )r   )rK   r   )r   r   rN   rC   r   Zget_revisionsrA   r   r   Zupgrade_ops_listr   Zdowngrade_ops_listr   r   Z_upgrade_opsrQ   r   r   Z_downgrade_opsr0   r/   r   r   r1   r   )	rV   r   r>   rK   r   r   r(   r2   hookr)   r)   r*   r     sT    







z RevisionContext._run_environmentrX   c                 C  sV   | j }tj|d pt |d tg tg |d |d |d |d |d d	}|S )	Nr-   r   r   r   r   r   r   )	r-   r   r'   r.   r   r   r   r   r   )r   r   r   r   r-   r   r0   )rV   r   opr)   r)   r*   r   L  s    z!RevisionContext._default_revisionzIterator[Optional[Script]]c                 c  s   | j D ]}| |V  qd S )N)r   r   )rV   Zgenerated_revisionr)   r)   r*   generate_scripts[  s    
z RevisionContext.generate_scripts)N)rx   ry   rz   r{   rW   r   r   r   r   r   r   r)   r)   r)   r*   r     s    8r   )r3   r4   Fr)   NN)0
__future__r   r}   typingr   r   r   r   r   r   r	   r
   r   Z
sqlalchemyr    r   r   r   
operationsr   Zsqlalchemy.enginer   r   r   Zsqlalchemy.sql.schemar   r   r   r   r   r   Zalembic.configr   Zalembic.operations.opsr   r   Zalembic.runtime.migrationr    Zalembic.script.baser!   r"   r+   r&   rE   rI   r/   r   r)   r)   r)   r*   <module>   sX   _!      & t