def _compare_indexes_and_uniques(schema, tname, object_filters, conn_table,
            metadata_table, diffs, autogen_context, inspector):

    is_create_table = conn_table is None

    # 1a. get raw indexes and unique constraints from metadata ...
    metadata_unique_constraints = set(uq for uq in metadata_table.constraints
            if isinstance(uq, sa_schema.UniqueConstraint)
    )
    metadata_indexes = set(metadata_table.indexes)

    # 1b. ... and from connection
    if conn_table is not None and hasattr(inspector, "get_unique_constraints"):
        try:
            conn_uniques = inspector.get_unique_constraints(tname)
        except (__HOLE__, NoSuchTableError):
            conn_uniques = []
    else:
        conn_uniques = []


    try:
        conn_indexes = inspector.get_indexes(tname)
    except NoSuchTableError:
        conn_indexes = []

    # 2. convert conn-level objects from raw inspector records
    # into schema objects
    conn_uniques = set(_make_unique_constraint(uq_def, conn_table)
                                    for uq_def in conn_uniques)
    conn_indexes = set(_make_index(ix, conn_table) for ix in conn_indexes)

    # 3. give the dialect a chance to omit indexes and constraints that
    # we know are either added implicitly by the DB or that the DB
    # can't accurately report on
    autogen_context['context'].impl.\
                                correct_for_autogen_constraints(
                                        conn_uniques, conn_indexes,
                                        metadata_unique_constraints,
                                        metadata_indexes
                                )

    # 4. organize the constraints into "signature" collections, the
    # _constraint_sig() objects provide a consistent facade over both
    # Index and UniqueConstraint so we can easily work with them
    # interchangeably
    metadata_unique_constraints = set(_uq_constraint_sig(uq)
                                    for uq in metadata_unique_constraints
                                    )

    metadata_indexes = set(_ix_constraint_sig(ix) for ix in metadata_indexes)

    conn_unique_constraints = set(_uq_constraint_sig(uq) for uq in conn_uniques)

    conn_indexes = set(_ix_constraint_sig(ix) for ix in conn_indexes)

    # 5. index things by name, for those objects that have names
    metadata_names = dict(
                        (c.name, c) for c in
                        metadata_unique_constraints.union(metadata_indexes)
                        if c.name is not None)

    conn_uniques_by_name = dict((c.name, c) for c in conn_unique_constraints)
    conn_indexes_by_name = dict((c.name, c) for c in conn_indexes)

    conn_names = dict((c.name, c) for c in
                    conn_unique_constraints.union(conn_indexes)
                            if c.name is not None)

    doubled_constraints = dict(
        (name, (conn_uniques_by_name[name], conn_indexes_by_name[name]))
        for name in set(conn_uniques_by_name).intersection(conn_indexes_by_name)
    )

    # 6. index things by "column signature", to help with unnamed unique
    # constraints.
    conn_uniques_by_sig = dict((uq.sig, uq) for uq in conn_unique_constraints)
    metadata_uniques_by_sig = dict(
                            (uq.sig, uq) for uq in metadata_unique_constraints)
    metadata_indexes_by_sig = dict(
                            (ix.sig, ix) for ix in metadata_indexes)
    unnamed_metadata_uniques = dict((uq.sig, uq) for uq in
                            metadata_unique_constraints if uq.name is None)

    # assumptions:
    # 1. a unique constraint or an index from the connection *always*
    #    has a name.
    # 2. an index on the metadata side *always* has a name.
    # 3. a unique constraint on the metadata side *might* have a name.
    # 4. The backend may double up indexes as unique constraints and
    #    vice versa (e.g. MySQL, Postgresql)

    def obj_added(obj):
        if obj.is_index:
            diffs.append(("add_index", obj.const))
            log.info("Detected added index '%s' on %s",
                obj.name, ', '.join([
                    "'%s'" % obj.column_names
                    ])
            )
        else:
            if is_create_table:
                # unique constraints are created inline with table defs
                return
            diffs.append(("add_constraint", obj.const))
            log.info("Detected added unique constraint '%s' on %s",
                obj.name, ', '.join([
                    "'%s'" % obj.column_names
                    ])
            )

    def obj_removed(obj):
        if obj.is_index:
            diffs.append(("remove_index", obj.const))
            log.info("Detected removed index '%s' on '%s'", obj.name, tname)
        else:
            diffs.append(("remove_constraint", obj.const))
            log.info("Detected removed unique constraint '%s' on '%s'",
                obj.name, tname
            )

    def obj_changed(old, new, msg):
        if old.is_index:
            log.info("Detected changed index '%s' on '%s':%s",
                    old.name, tname, ', '.join(msg)
                )
            diffs.append(("remove_index", old.const))
            diffs.append(("add_index", new.const))
        else:
            log.info("Detected changed unique constraint '%s' on '%s':%s",
                    old.name, tname, ', '.join(msg)
                )
            diffs.append(("remove_constraint", old.const))
            diffs.append(("add_constraint", new.const))


    for added_name in sorted(set(metadata_names).difference(conn_names)):
        obj = metadata_names[added_name]
        obj_added(obj)


    for existing_name in sorted(set(metadata_names).intersection(conn_names)):
        metadata_obj = metadata_names[existing_name]

        if existing_name in doubled_constraints:
            conn_uq, conn_idx = doubled_constraints[existing_name]
            if metadata_obj.is_index:
                conn_obj = conn_idx
            else:
                conn_obj = conn_uq
        else:
            conn_obj = conn_names[existing_name]

        if conn_obj.is_index != metadata_obj.is_index:
            obj_removed(conn_obj)
            obj_added(metadata_obj)
        else:
            msg = []
            if conn_obj.is_unique != metadata_obj.is_unique:
                msg.append(' unique=%r to unique=%r' % (
                    conn_obj.is_unique, metadata_obj.is_unique
                ))
            if conn_obj.sig != metadata_obj.sig:
                msg.append(' columns %r to %r' % (
                    conn_obj.sig, metadata_obj.sig
                ))

            if msg:
                obj_changed(conn_obj, metadata_obj, msg)


    for removed_name in sorted(set(conn_names).difference(metadata_names)):
        conn_obj = conn_names[removed_name]
        if not conn_obj.is_index and conn_obj.sig in unnamed_metadata_uniques:
            continue
        elif removed_name in doubled_constraints:
            if conn_obj.sig not in metadata_indexes_by_sig and \
                conn_obj.sig not in metadata_uniques_by_sig:
                conn_uq, conn_idx = doubled_constraints[removed_name]
                obj_removed(conn_uq)
                obj_removed(conn_idx)
        else:
            obj_removed(conn_obj)

    for uq_sig in unnamed_metadata_uniques:
        if uq_sig not in conn_uniques_by_sig:
            obj_added(unnamed_metadata_uniques[uq_sig])
dataset/ETHPy150Open RoseOu/flasky/venv/lib/python2.7/site-packages/alembic/autogenerate/compare.py/_compare_indexes_and_uniques