from sqlalchemy.testing import assert_raises
from sqlalchemy.testing import assert_raises_message
from sqlalchemy.testing import emits_warning

import pickle
from sqlalchemy import Integer, String, UniqueConstraint, \
    CheckConstraint, ForeignKey, MetaData, Sequence, \
    ForeignKeyConstraint, ColumnDefault, Index, event,\
    events, Unicode, types as sqltypes
from sqlalchemy.testing.schema import Table, Column
from sqlalchemy import schema, exc
import sqlalchemy as tsa
from sqlalchemy.testing import fixtures
from sqlalchemy import testing
from sqlalchemy.testing import ComparesTables, AssertsCompiledSQL
from sqlalchemy.testing import eq_, is_

class MetaDataTest(fixtures.TestBase, ComparesTables):
    def test_metadata_connect(self):
        metadata = MetaData()
        t1 = Table('table1', metadata,
            Column('col1', Integer, primary_key=True),
            Column('col2', String(20)))
        metadata.bind = testing.db
        metadata.create_all()
        try:
            assert t1.count().scalar() == 0
        finally:
            metadata.drop_all()

    def test_metadata_contains(self):
        metadata = MetaData()
        t1 = Table('t1', metadata, Column('x', Integer))
        t2 = Table('t2', metadata, Column('x', Integer), schema='foo')
        t3 = Table('t2', MetaData(), Column('x', Integer))
        t4 = Table('t1', MetaData(), Column('x', Integer), schema='foo')

        assert "t1" in metadata
        assert "foo.t2" in metadata
        assert "t2" not in metadata
        assert "foo.t1" not in metadata
        assert t1 in metadata
        assert t2 in metadata
        assert t3 not in metadata
        assert t4 not in metadata

    def test_uninitialized_column_copy(self):
        for col in [
            Column('foo', String(), nullable=False),
            Column('baz', String(), unique=True),
            Column(Integer(), primary_key=True),
            Column('bar', Integer(), Sequence('foo_seq'), primary_key=True,
                                                            key='bar'),
            Column(Integer(), ForeignKey('bat.blah'), doc="this is a col"),
            Column('bar', Integer(), ForeignKey('bat.blah'), primary_key=True,
                                                            key='bar'),
            Column('bar', Integer(), info={'foo': 'bar'}),
        ]:
            c2 = col.copy()
            for attr in ('name', 'type', 'nullable',
                        'primary_key', 'key', 'unique', 'info',
                        'doc'):
                eq_(getattr(col, attr), getattr(c2, attr))
            eq_(len(col.foreign_keys), len(c2.foreign_keys))
            if col.default:
                eq_(c2.default.name, 'foo_seq')
            for a1, a2 in zip(col.foreign_keys, c2.foreign_keys):
                assert a1 is not a2
                eq_(a2._colspec, 'bat.blah')

    def test_col_subclass_copy(self):
        class MyColumn(schema.Column):
            def __init__(self, *args, **kw):
                self.widget = kw.pop('widget', None)
                super(MyColumn, self).__init__(*args, **kw)

            def copy(self, *arg, **kw):
                c = super(MyColumn, self).copy(*arg, **kw)
                c.widget = self.widget
                return c
        c1 = MyColumn('foo', Integer, widget='x')
        c2 = c1.copy()
        assert isinstance(c2, MyColumn)
        eq_(c2.widget, 'x')

    def test_uninitialized_column_copy_events(self):
        msgs = []
        def write(c, t):
            msgs.append("attach %s.%s" % (t.name, c.name))
        c1 = Column('foo', String())
        m = MetaData()
        for i in xrange(3):
            cx = c1.copy()
            # as of 0.7, these events no longer copy.  its expected
            # that listeners will be re-established from the
            # natural construction of things.
            cx._on_table_attach(write)
            Table('foo%d' % i, m, cx)
        eq_(msgs, ['attach foo0.foo', 'attach foo1.foo', 'attach foo2.foo'])

    def test_schema_collection_add(self):
        metadata = MetaData()

        Table('t1', metadata, Column('x', Integer), schema='foo')
        Table('t2', metadata, Column('x', Integer), schema='bar')
        Table('t3', metadata, Column('x', Integer))

        eq_(metadata._schemas, set(['foo', 'bar']))
        eq_(len(metadata.tables), 3)

    def test_schema_collection_remove(self):
        metadata = MetaData()

        t1 = Table('t1', metadata, Column('x', Integer), schema='foo')
        Table('t2', metadata, Column('x', Integer), schema='bar')
        t3 = Table('t3', metadata, Column('x', Integer), schema='bar')

        metadata.remove(t3)
        eq_(metadata._schemas, set(['foo', 'bar']))
        eq_(len(metadata.tables), 2)

        metadata.remove(t1)
        eq_(metadata._schemas, set(['bar']))
        eq_(len(metadata.tables), 1)

    def test_schema_collection_remove_all(self):
        metadata = MetaData()

        Table('t1', metadata, Column('x', Integer), schema='foo')
        Table('t2', metadata, Column('x', Integer), schema='bar')

        metadata.clear()
        eq_(metadata._schemas, set())
        eq_(len(metadata.tables), 0)

    def test_metadata_tables_immutable(self):
        metadata = MetaData()

        Table('t1', metadata, Column('x', Integer))
        assert 't1' in metadata.tables

        assert_raises(
            TypeError,
            lambda: metadata.tables.pop('t1')
        )

    @testing.provide_metadata
    def test_dupe_tables(self):
        metadata = self.metadata
        Table('table1', metadata,
                Column('col1', Integer, primary_key=True),
                Column('col2', String(20)))

        metadata.create_all()
        Table('table1', metadata, autoload=True)
        def go():
            Table('table1', metadata,
                    Column('col1', Integer, primary_key=True),
                    Column('col2', String(20)))
        assert_raises_message(
            tsa.exc.InvalidRequestError,
                "Table 'table1' is already defined for this "
                "MetaData instance.  Specify 'extend_existing=True' "
                "to redefine options and columns on an existing "
                "Table object.",
            go
        )

    def test_fk_copy(self):
        c1 = Column('foo', Integer)
        c2 = Column('bar', Integer)
        m = MetaData()
        t1 = Table('t', m, c1, c2)

        kw = dict(onupdate="X",
                        ondelete="Y", use_alter=True, name='f1',
                        deferrable="Z", initially="Q", link_to_name=True)

        fk1 = ForeignKey(c1, **kw)
        fk2 = ForeignKeyConstraint((c1,), (c2,), **kw)

        t1.append_constraint(fk2)
        fk1c = fk1.copy()
        fk2c = fk2.copy()

        for k in kw:
            eq_(getattr(fk1c, k), kw[k])
            eq_(getattr(fk2c, k), kw[k])

    def test_check_constraint_copy(self):
        r = lambda x: x
        c = CheckConstraint("foo bar",
                            name='name',
                            initially=True,
                            deferrable=True,
                            _create_rule=r)
        c2 = c.copy()
        eq_(c2.name, 'name')
        eq_(str(c2.sqltext), "foo bar")
        eq_(c2.initially, True)
        eq_(c2.deferrable, True)
        assert c2._create_rule is r

    def test_col_replace_w_constraint(self):
        m = MetaData()
        a = Table('a', m, Column('id', Integer, primary_key=True))

        aid = Column('a_id', ForeignKey('a.id'))
        b = Table('b', m, aid)
        b.append_column(aid)

        assert b.c.a_id.references(a.c.id)
        eq_(len(b.constraints), 2)

    def test_fk_construct(self):
        c1 = Column('foo', Integer)
        c2 = Column('bar', Integer)
        m = MetaData()
        t1 = Table('t', m, c1, c2)
        fk1 = ForeignKeyConstraint(('foo', ), ('bar', ), table=t1)
        assert fk1 in t1.constraints

    def test_fk_no_such_parent_col_error(self):
        meta = MetaData()
        a = Table('a', meta, Column('a', Integer))
        Table('b', meta, Column('b', Integer))

        def go():
            a.append_constraint(
                ForeignKeyConstraint(['x'], ['b.b'])
            )
        assert_raises_message(
            exc.ArgumentError,
            "Can't create ForeignKeyConstraint on "
            "table 'a': no column named 'x' is present.",
            go
        )

    def test_fk_no_such_target_col_error(self):
        meta = MetaData()
        a = Table('a', meta, Column('a', Integer))
        Table('b', meta, Column('b', Integer))
        a.append_constraint(
            ForeignKeyConstraint(['a'], ['b.x'])
        )

        def go():
            list(a.c.a.foreign_keys)[0].column
        assert_raises_message(
            exc.NoReferencedColumnError,
            "Could not create ForeignKey 'b.x' on "
            "table 'a': table 'b' has no column named 'x'",
            go
        )

    @testing.exclude('mysql', '<', (4, 1, 1), 'early types are squirrely')
    def test_to_metadata(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('myid', Integer, Sequence('foo_id_seq'), primary_key=True),
            Column('name', String(40), nullable=True),
            Column('foo', String(40), nullable=False, server_default='x',
                                                        server_onupdate='q'),
            Column('bar', String(40), nullable=False, default='y',
                                                        onupdate='z'),
            Column('description', String(30),
                                    CheckConstraint("description='hi'")),
            UniqueConstraint('name'),
            test_needs_fk=True,
        )

        table2 = Table('othertable', meta,
            Column('id', Integer, Sequence('foo_seq'), primary_key=True),
            Column('myid', Integer,
                        ForeignKey('mytable.myid'),
                    ),
            test_needs_fk=True,
            )

        def test_to_metadata():
            meta2 = MetaData()
            table_c = table.tometadata(meta2)
            table2_c = table2.tometadata(meta2)
            return (table_c, table2_c)

        def test_pickle():
            meta.bind = testing.db
            meta2 = pickle.loads(pickle.dumps(meta))
            assert meta2.bind is None
            pickle.loads(pickle.dumps(meta2))
            return (meta2.tables['mytable'], meta2.tables['othertable'])

        def test_pickle_via_reflect():
            # this is the most common use case, pickling the results of a
            # database reflection
            meta2 = MetaData(bind=testing.db)
            t1 = Table('mytable', meta2, autoload=True)
            Table('othertable', meta2, autoload=True)
            meta3 = pickle.loads(pickle.dumps(meta2))
            assert meta3.bind is None
            assert meta3.tables['mytable'] is not t1

            return (meta3.tables['mytable'], meta3.tables['othertable'])

        meta.create_all(testing.db)
        try:
            for test, has_constraints, reflect in \
                    (test_to_metadata, True, False), \
                    (test_pickle, True, False), \
                    (test_pickle_via_reflect, False, True):
                table_c, table2_c = test()
                self.assert_tables_equal(table, table_c)
                self.assert_tables_equal(table2, table2_c)
                assert table is not table_c
                assert table.primary_key is not table_c.primary_key
                assert list(table2_c.c.myid.foreign_keys)[0].column \
                    is table_c.c.myid
                assert list(table2_c.c.myid.foreign_keys)[0].column \
                    is not table.c.myid
                assert 'x' in str(table_c.c.foo.server_default.arg)
                if not reflect:
                    assert isinstance(table_c.c.myid.default, Sequence)
                    assert str(table_c.c.foo.server_onupdate.arg) == 'q'
                    assert str(table_c.c.bar.default.arg) == 'y'
                    assert getattr(table_c.c.bar.onupdate.arg, 'arg',
                                   table_c.c.bar.onupdate.arg) == 'z'
                    assert isinstance(table2_c.c.id.default, Sequence)

                # constraints dont get reflected for any dialect right
                # now

                if has_constraints:
                    for c in table_c.c.description.constraints:
                        if isinstance(c, CheckConstraint):
                            break
                    else:
                        assert False
                    assert str(c.sqltext) == "description='hi'"
                    for c in table_c.constraints:
                        if isinstance(c, UniqueConstraint):
                            break
                    else:
                        assert False
                    assert c.columns.contains_column(table_c.c.name)
                    assert not c.columns.contains_column(table.c.name)

        finally:
            meta.drop_all(testing.db)

    def test_col_key_fk_parent_tometadata(self):
        # test #2643
        m1 = MetaData()
        a = Table('a', m1, Column('x', Integer))
        b = Table('b', m1, Column('x', Integer, ForeignKey('a.x'), key='y'))
        assert b.c.y.references(a.c.x)

        m2 = MetaData()
        b2 = b.tometadata(m2)
        a2 = a.tometadata(m2)
        assert b2.c.y.references(a2.c.x)

    def test_pickle_metadata_sequence_restated(self):
        m1 = MetaData()
        Table('a', m1,
             Column('id', Integer, primary_key=True),
             Column('x', Integer, Sequence("x_seq")))

        m2 = pickle.loads(pickle.dumps(m1))

        s2 = Sequence("x_seq")
        t2 = Table('a', m2,
             Column('id', Integer, primary_key=True),
             Column('x', Integer, s2),
             extend_existing=True)

        assert m2._sequences['x_seq'] is t2.c.x.default
        assert m2._sequences['x_seq'] is s2

    def test_sequence_restated_replaced(self):
        """Test restatement of Sequence replaces."""

        m1 = MetaData()
        s1 = Sequence("x_seq")
        t = Table('a', m1,
             Column('x', Integer, s1)
        )
        assert m1._sequences['x_seq'] is s1

        s2 = Sequence('x_seq')
        Table('a', m1,
             Column('x', Integer, s2),
             extend_existing=True
        )
        assert t.c.x.default is s2
        assert m1._sequences['x_seq'] is s2

    def test_pickle_metadata_sequence_implicit(self):
        m1 = MetaData()
        Table('a', m1,
             Column('id', Integer, primary_key=True),
             Column('x', Integer, Sequence("x_seq")))

        m2 = pickle.loads(pickle.dumps(m1))

        t2 = Table('a', m2, extend_existing=True)

        eq_(m2._sequences, {'x_seq': t2.c.x.default})

    def test_pickle_metadata_schema(self):
        m1 = MetaData()
        Table('a', m1,
             Column('id', Integer, primary_key=True),
             Column('x', Integer, Sequence("x_seq")),
             schema='y')

        m2 = pickle.loads(pickle.dumps(m1))

        Table('a', m2, schema='y',
             extend_existing=True)

        eq_(m2._schemas, m1._schemas)

    def test_tometadata_with_schema(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('myid', Integer, primary_key=True),
            Column('name', String(40), nullable=True),
            Column('description', String(30),
                            CheckConstraint("description='hi'")),
            UniqueConstraint('name'),
            test_needs_fk=True,
        )

        table2 = Table('othertable', meta,
            Column('id', Integer, primary_key=True),
            Column('myid', Integer, ForeignKey('mytable.myid')),
            test_needs_fk=True,
            )

        meta2 = MetaData()
        table_c = table.tometadata(meta2, schema='someschema')
        table2_c = table2.tometadata(meta2, schema='someschema')

        eq_(str(table_c.join(table2_c).onclause), str(table_c.c.myid
            == table2_c.c.myid))
        eq_(str(table_c.join(table2_c).onclause),
            'someschema.mytable.myid = someschema.othertable.myid')

    def test_tometadata_with_default_schema(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('myid', Integer, primary_key=True),
            Column('name', String(40), nullable=True),
            Column('description', String(30),
                        CheckConstraint("description='hi'")),
            UniqueConstraint('name'),
            test_needs_fk=True,
            schema='myschema',
        )

        table2 = Table('othertable', meta,
            Column('id', Integer, primary_key=True),
            Column('myid', Integer, ForeignKey('myschema.mytable.myid')),
            test_needs_fk=True,
            schema='myschema',
            )

        meta2 = MetaData()
        table_c = table.tometadata(meta2)
        table2_c = table2.tometadata(meta2)

        eq_(str(table_c.join(table2_c).onclause), str(table_c.c.myid
            == table2_c.c.myid))
        eq_(str(table_c.join(table2_c).onclause),
            'myschema.mytable.myid = myschema.othertable.myid')

    def test_tometadata_kwargs(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('myid', Integer, primary_key=True),
            mysql_engine='InnoDB',
        )

        meta2 = MetaData()
        table_c = table.tometadata(meta2)

        eq_(table.kwargs, table_c.kwargs)

    def test_tometadata_indexes(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('id', Integer, primary_key=True),
            Column('data1', Integer, index=True),
            Column('data2', Integer),
        )
        Index('multi', table.c.data1, table.c.data2),

        meta2 = MetaData()
        table_c = table.tometadata(meta2)

        def _get_key(i):
            return [i.name, i.unique] + \
                    sorted(i.kwargs.items()) + \
                    i.columns.keys()

        eq_(
            sorted([_get_key(i) for i in table.indexes]),
            sorted([_get_key(i) for i in table_c.indexes])
        )

    @emits_warning("Table '.+' already exists within the given MetaData")
    def test_tometadata_already_there(self):

        meta1 = MetaData()
        table1 = Table('mytable', meta1,
            Column('myid', Integer, primary_key=True),
        )
        meta2 = MetaData()
        table2 = Table('mytable', meta2,
            Column('yourid', Integer, primary_key=True),
        )

        table_c = table1.tometadata(meta2)
        table_d = table2.tometadata(meta2)

        # d'oh!
        assert table_c is table_d

    def test_metadata_schema_arg(self):
        m1 = MetaData(schema='sch1')
        m2 = MetaData(schema='sch1', quote_schema=True)
        m3 = MetaData(schema='sch1', quote_schema=False)
        m4 = MetaData()

        for i, (name, metadata, schema, quote_schema,
                        exp_schema, exp_quote_schema) in enumerate([
                                ('t1', m1, None, None, 'sch1', None),
                                ('t2', m1, 'sch2', None, 'sch2', None),
                                ('t3', m1, 'sch2', True, 'sch2', True),
                                ('t4', m1, 'sch1', None, 'sch1', None),
                                ('t1', m2, None, None, 'sch1', True),
                                ('t2', m2, 'sch2', None, 'sch2', None),
                                ('t3', m2, 'sch2', True, 'sch2', True),
                                ('t4', m2, 'sch1', None, 'sch1', None),
                                ('t1', m3, None, None, 'sch1', False),
                                ('t2', m3, 'sch2', None, 'sch2', None),
                                ('t3', m3, 'sch2', True, 'sch2', True),
                                ('t4', m3, 'sch1', None, 'sch1', None),
                                ('t1', m4, None, None, None, None),
                                ('t2', m4, 'sch2', None, 'sch2', None),
                                ('t3', m4, 'sch2', True, 'sch2', True),
                                ('t4', m4, 'sch1', None, 'sch1', None),
                        ]):
            kw = {}
            if schema is not None:
                kw['schema'] = schema
            if quote_schema is not None:
                kw['quote_schema'] = quote_schema
            t = Table(name, metadata, **kw)
            eq_(t.schema, exp_schema, "test %d, table schema" % i)
            eq_(t.quote_schema, exp_quote_schema,
                            "test %d, table quote_schema" % i)
            seq = Sequence(name, metadata=metadata, **kw)
            eq_(seq.schema, exp_schema, "test %d, seq schema" % i)
            eq_(seq.quote_schema, exp_quote_schema,
                            "test %d, seq quote_schema" % i)

    def test_manual_dependencies(self):
        meta = MetaData()
        a = Table('a', meta, Column('foo', Integer))
        b = Table('b', meta, Column('foo', Integer))
        c = Table('c', meta, Column('foo', Integer))
        d = Table('d', meta, Column('foo', Integer))
        e = Table('e', meta, Column('foo', Integer))

        e.add_is_dependent_on(c)
        a.add_is_dependent_on(b)
        b.add_is_dependent_on(d)
        e.add_is_dependent_on(b)
        c.add_is_dependent_on(a)
        eq_(
            meta.sorted_tables,
            [d, b, a, c, e]
        )

    def test_tometadata_default_schema_metadata(self):
        meta = MetaData(schema='myschema')

        table = Table('mytable', meta,
            Column('myid', Integer, primary_key=True),
            Column('name', String(40), nullable=True),
            Column('description', String(30), CheckConstraint("description='hi'")),
            UniqueConstraint('name'),
            test_needs_fk=True
        )

        table2 = Table('othertable', meta,
            Column('id', Integer, primary_key=True),
            Column('myid', Integer, ForeignKey('myschema.mytable.myid')),
            test_needs_fk=True
            )

        meta2 = MetaData(schema='someschema')
        table_c = table.tometadata(meta2, schema=None)
        table2_c = table2.tometadata(meta2, schema=None)

        eq_(str(table_c.join(table2_c).onclause),
                str(table_c.c.myid == table2_c.c.myid))
        eq_(str(table_c.join(table2_c).onclause),
                "someschema.mytable.myid = someschema.othertable.myid")

    def test_tometadata_strip_schema(self):
        meta = MetaData()

        table = Table('mytable', meta,
            Column('myid', Integer, primary_key=True),
            Column('name', String(40), nullable=True),
            Column('description', String(30),
                        CheckConstraint("description='hi'")),
            UniqueConstraint('name'),
            test_needs_fk=True,
        )

        table2 = Table('othertable', meta,
            Column('id', Integer, primary_key=True),
            Column('myid', Integer, ForeignKey('mytable.myid')),
            test_needs_fk=True,
            )

        meta2 = MetaData()
        table_c = table.tometadata(meta2, schema=None)
        table2_c = table2.tometadata(meta2, schema=None)

        eq_(str(table_c.join(table2_c).onclause), str(table_c.c.myid
            == table2_c.c.myid))
        eq_(str(table_c.join(table2_c).onclause),
            'mytable.myid = othertable.myid')

    def test_nonexistent(self):
        assert_raises(tsa.exc.NoSuchTableError, Table,
                          'fake_table',
                          MetaData(testing.db), autoload=True)

    def test_assorted_repr(self):
        t1 = Table("foo", MetaData(), Column("x", Integer))
        i1 = Index("bar", t1.c.x)
        ck = schema.CheckConstraint("x > y", name="someconstraint")

        for const, exp in (
            (Sequence("my_seq"),
                "Sequence('my_seq')"),
            (Sequence("my_seq", start=5),
                "Sequence('my_seq', start=5)"),
            (Column("foo", Integer),
                "Column('foo', Integer(), table=None)"),
            (Table("bar", MetaData(), Column("x", String)),
                "Table('bar', MetaData(bind=None), "
                "Column('x', String(), table=<bar>), schema=None)"),
            (schema.DefaultGenerator(for_update=True),
                "DefaultGenerator(for_update=True)"),
            (schema.Index("bar", "c"), "Index('bar')"),
            (i1, "Index('bar', Column('x', Integer(), table=<foo>))"),
            (schema.FetchedValue(), "FetchedValue()"),
            (ck,
                    "CheckConstraint("
                    "%s"
                    ", name='someconstraint')" % repr(ck.sqltext)),
        ):
            eq_(
                repr(const),
                exp
            )

class TableTest(fixtures.TestBase, AssertsCompiledSQL):
    @testing.skip_if('mssql', 'different col format')
    def test_prefixes(self):
        from sqlalchemy import Table
        table1 = Table("temporary_table_1", MetaData(),
                      Column("col1", Integer),
                      prefixes=["TEMPORARY"])

        self.assert_compile(
            schema.CreateTable(table1),
            "CREATE TEMPORARY TABLE temporary_table_1 (col1 INTEGER)"
        )

        table2 = Table("temporary_table_2", MetaData(),
                      Column("col1", Integer),
                      prefixes=["VIRTUAL"])
        self.assert_compile(
            schema.CreateTable(table2),
            "CREATE VIRTUAL TABLE temporary_table_2 (col1 INTEGER)"
        )

    def test_table_info(self):
        metadata = MetaData()
        t1 = Table('foo', metadata, info={'x': 'y'})
        t2 = Table('bar', metadata, info={})
        t3 = Table('bat', metadata)
        assert t1.info == {'x': 'y'}
        assert t2.info == {}
        assert t3.info == {}
        for t in (t1, t2, t3):
            t.info['bar'] = 'zip'
            assert t.info['bar'] == 'zip'

    def test_c_immutable(self):
        m = MetaData()
        t1 = Table('t', m, Column('x', Integer), Column('y', Integer))
        assert_raises(
            TypeError,
            t1.c.extend, [Column('z', Integer)]
        )

        def assign():
            t1.c['z'] = Column('z', Integer)
        assert_raises(
            TypeError,
            assign
        )

        def assign2():
            t1.c.z = Column('z', Integer)
        assert_raises(
            TypeError,
            assign2
        )

    def test_autoincrement_replace(self):
        m = MetaData()

        t = Table('t', m,
            Column('id', Integer, primary_key=True)
        )

        is_(t._autoincrement_column, t.c.id)

        t = Table('t', m,
            Column('id', Integer, primary_key=True),
            extend_existing=True
        )
        is_(t._autoincrement_column, t.c.id)

class SchemaTypeTest(fixtures.TestBase):
    class MyType(sqltypes.SchemaType, sqltypes.TypeEngine):
        column = None
        table = None
        evt_targets = ()

        def _set_table(self, column, table):
            super(SchemaTypeTest.MyType, self)._set_table(column, table)
            self.column = column
            self.table = table

        def _on_table_create(self, target, bind, **kw):
            self.evt_targets += (target,)

    def test_independent_schema(self):
        m = MetaData()
        type_ = self.MyType(schema="q")
        t1 = Table('x', m, Column("y", type_), schema="z")
        eq_(t1.c.y.type.schema, "q")

    def test_inherit_schema(self):
        m = MetaData()
        type_ = self.MyType(schema="q", inherit_schema=True)
        t1 = Table('x', m, Column("y", type_), schema="z")
        eq_(t1.c.y.type.schema, "z")

    def test_independent_schema_enum(self):
        m = MetaData()
        type_ = sqltypes.Enum("a", schema="q")
        t1 = Table('x', m, Column("y", type_), schema="z")
        eq_(t1.c.y.type.schema, "q")

    def test_inherit_schema_enum(self):
        m = MetaData()
        type_ = sqltypes.Enum("a", "b", "c", schema="q", inherit_schema=True)
        t1 = Table('x', m, Column("y", type_), schema="z")
        eq_(t1.c.y.type.schema, "z")

    def test_tometadata_copy_type(self):
        m1 = MetaData()

        type_ = self.MyType()
        t1 = Table('x', m1, Column("y", type_))

        m2 = MetaData()
        t2 = t1.tometadata(m2)

        # metadata isn't set
        is_(t2.c.y.type.metadata, None)

        # our test type sets table, though
        is_(t2.c.y.type.table, t2)

    def test_tometadata_independent_schema(self):
        m1 = MetaData()

        type_ = self.MyType()
        t1 = Table('x', m1, Column("y", type_))

        m2 = MetaData()
        t2 = t1.tometadata(m2, schema="bar")

        eq_(t2.c.y.type.schema, None)

    def test_tometadata_inherit_schema(self):
        m1 = MetaData()

        type_ = self.MyType(inherit_schema=True)
        t1 = Table('x', m1, Column("y", type_))

        m2 = MetaData()
        t2 = t1.tometadata(m2, schema="bar")

        eq_(t1.c.y.type.schema, None)
        eq_(t2.c.y.type.schema, "bar")

    def test_tometadata_independent_events(self):
        m1 = MetaData()

        type_ = self.MyType()
        t1 = Table('x', m1, Column("y", type_))

        m2 = MetaData()
        t2 = t1.tometadata(m2)

        t1.dispatch.before_create(t1, testing.db)
        eq_(t1.c.y.type.evt_targets, (t1,))
        eq_(t2.c.y.type.evt_targets, ())

        t2.dispatch.before_create(t2, testing.db)
        t2.dispatch.before_create(t2, testing.db)
        eq_(t1.c.y.type.evt_targets, (t1,))
        eq_(t2.c.y.type.evt_targets, (t2, t2))

class SchemaTest(fixtures.TestBase, AssertsCompiledSQL):

    def test_default_schema_metadata_fk(self):
        m = MetaData(schema="foo")
        t1 = Table('t1', m, Column('x', Integer))
        t2 = Table('t2', m, Column('x', Integer, ForeignKey('t1.x')))
        assert t2.c.x.references(t1.c.x)

    def test_ad_hoc_schema_equiv_fk(self):
        m = MetaData()
        t1 = Table('t1', m, Column('x', Integer), schema="foo")
        t2 = Table('t2', m, Column('x', Integer, ForeignKey('t1.x')), schema="foo")
        assert_raises(
            exc.NoReferencedTableError,
            lambda: t2.c.x.references(t1.c.x)
        )

    def test_default_schema_metadata_fk_alt_remote(self):
        m = MetaData(schema="foo")
        t1 = Table('t1', m, Column('x', Integer))
        t2 = Table('t2', m, Column('x', Integer, ForeignKey('t1.x')),
                                schema="bar")
        assert t2.c.x.references(t1.c.x)

    def test_default_schema_metadata_fk_alt_local_raises(self):
        m = MetaData(schema="foo")
        t1 = Table('t1', m, Column('x', Integer), schema="bar")
        t2 = Table('t2', m, Column('x', Integer, ForeignKey('t1.x')))
        assert_raises(
            exc.NoReferencedTableError,
            lambda: t2.c.x.references(t1.c.x)
        )

    def test_default_schema_metadata_fk_alt_local(self):
        m = MetaData(schema="foo")
        t1 = Table('t1', m, Column('x', Integer), schema="bar")
        t2 = Table('t2', m, Column('x', Integer, ForeignKey('bar.t1.x')))
        assert t2.c.x.references(t1.c.x)

    def test_create_drop_schema(self):

        self.assert_compile(
            schema.CreateSchema("sa_schema"),
            "CREATE SCHEMA sa_schema"
        )
        self.assert_compile(
            schema.DropSchema("sa_schema"),
            "DROP SCHEMA sa_schema"
        )
        self.assert_compile(
            schema.DropSchema("sa_schema", cascade=True),
            "DROP SCHEMA sa_schema CASCADE"
        )

    def test_iteration(self):
        metadata = MetaData()
        table1 = Table('table1', metadata, Column('col1', Integer,
                       primary_key=True), schema='someschema')
        table2 = Table('table2', metadata, Column('col1', Integer,
                       primary_key=True), Column('col2', Integer,
                       ForeignKey('someschema.table1.col1')),
                       schema='someschema')

        t1 = str(schema.CreateTable(table1).compile(bind=testing.db))
        t2 = str(schema.CreateTable(table2).compile(bind=testing.db))
        if testing.db.dialect.preparer(testing.db.dialect).omit_schema:
            assert t1.index("CREATE TABLE table1") > -1
            assert t2.index("CREATE TABLE table2") > -1
        else:
            assert t1.index("CREATE TABLE someschema.table1") > -1
            assert t2.index("CREATE TABLE someschema.table2") > -1

class UseExistingTest(fixtures.TablesTest):
    @classmethod
    def define_tables(cls, metadata):
        Table('users', metadata,
                    Column('id', Integer, primary_key=True),
                    Column('name', String(30)))

    def _useexisting_fixture(self):
        meta2 = MetaData(testing.db)
        Table('users', meta2, autoload=True)
        return meta2

    def _notexisting_fixture(self):
        return MetaData(testing.db)

    def test_exception_no_flags(self):
        meta2 = self._useexisting_fixture()
        def go():
            Table('users', meta2, Column('name',
                          Unicode), autoload=True)
        assert_raises_message(
            exc.InvalidRequestError,
                "Table 'users' is already defined for this "\
                "MetaData instance.",
            go
        )

    @testing.uses_deprecated
    def test_deprecated_useexisting(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      autoload=True, useexisting=True)
        assert isinstance(users.c.name.type, Unicode)
        assert not users.quote
        users = Table('users', meta2, quote=True, autoload=True,
                      useexisting=True)
        assert users.quote

    def test_keep_plus_existing_raises(self):
        meta2 = self._useexisting_fixture()
        assert_raises(
            exc.ArgumentError,
            Table, 'users', meta2, keep_existing=True,
                extend_existing=True
        )

    @testing.uses_deprecated
    def test_existing_plus_useexisting_raises(self):
        meta2 = self._useexisting_fixture()
        assert_raises(
            exc.ArgumentError,
            Table, 'users', meta2, useexisting=True,
                extend_existing=True
        )

    def test_keep_existing_no_dupe_constraints(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2,
            Column('id', Integer),
            Column('name', Unicode),
            UniqueConstraint('name'),
            keep_existing=True
        )
        assert 'name' in users.c
        assert 'id' in users.c
        eq_(len(users.constraints), 2)

        u2 = Table('users', meta2,
            Column('id', Integer),
            Column('name', Unicode),
            UniqueConstraint('name'),
            keep_existing=True
        )
        eq_(len(u2.constraints), 2)

    def test_extend_existing_dupes_constraints(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2,
            Column('id', Integer),
            Column('name', Unicode),
            UniqueConstraint('name'),
            extend_existing=True
        )
        assert 'name' in users.c
        assert 'id' in users.c
        eq_(len(users.constraints), 2)

        u2 = Table('users', meta2,
            Column('id', Integer),
            Column('name', Unicode),
            UniqueConstraint('name'),
            extend_existing=True
        )
        # constraint got duped
        eq_(len(u2.constraints), 3)

    def test_keep_existing_coltype(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      autoload=True, keep_existing=True)
        assert not isinstance(users.c.name.type, Unicode)

    def test_keep_existing_quote(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, quote=True, autoload=True,
                      keep_existing=True)
        assert not users.quote

    def test_keep_existing_add_column(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                        autoload=True,
                      keep_existing=True)
        assert "foo" not in users.c

    def test_keep_existing_coltype_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      autoload=True, keep_existing=True)
        assert isinstance(users.c.name.type, Unicode)

    def test_keep_existing_quote_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2, quote=True,
                        autoload=True,
                      keep_existing=True)
        assert users.quote

    def test_keep_existing_add_column_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                        autoload=True,
                      keep_existing=True)
        assert "foo" in users.c

    def test_keep_existing_coltype_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      keep_existing=True)
        assert not isinstance(users.c.name.type, Unicode)

    def test_keep_existing_quote_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, quote=True,
                      keep_existing=True)
        assert not users.quote

    def test_keep_existing_add_column_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                      keep_existing=True)
        assert "foo" not in users.c

    def test_extend_existing_coltype(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      autoload=True, extend_existing=True)
        assert isinstance(users.c.name.type, Unicode)

    def test_extend_existing_quote(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, quote=True, autoload=True,
                      extend_existing=True)
        assert users.quote

    def test_extend_existing_add_column(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                        autoload=True,
                      extend_existing=True)
        assert "foo" in users.c

    def test_extend_existing_coltype_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      autoload=True, extend_existing=True)
        assert isinstance(users.c.name.type, Unicode)

    def test_extend_existing_quote_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2, quote=True,
                        autoload=True,
                      extend_existing=True)
        assert users.quote

    def test_extend_existing_add_column_no_orig(self):
        meta2 = self._notexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                        autoload=True,
                      extend_existing=True)
        assert "foo" in users.c

    def test_extend_existing_coltype_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, Column('name', Unicode),
                      extend_existing=True)
        assert isinstance(users.c.name.type, Unicode)

    def test_extend_existing_quote_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2, quote=True,
                      extend_existing=True)
        assert users.quote

    def test_extend_existing_add_column_no_reflection(self):
        meta2 = self._useexisting_fixture()
        users = Table('users', meta2,
                        Column('foo', Integer),
                      extend_existing=True)
        assert "foo" in users.c

class ConstraintTest(fixtures.TestBase):
    def _single_fixture(self):
        m = MetaData()

        t1 = Table('t1', m,
            Column('a', Integer),
            Column('b', Integer)
        )

        t2 = Table('t2', m,
            Column('a', Integer, ForeignKey('t1.a'))
        )

        t3 = Table('t3', m,
            Column('a', Integer)
        )
        return t1, t2, t3

    def test_table_references(self):
        t1, t2, t3 = self._single_fixture()
        assert list(t2.c.a.foreign_keys)[0].references(t1)
        assert not list(t2.c.a.foreign_keys)[0].references(t3)

    def test_column_references(self):
        t1, t2, t3 = self._single_fixture()
        assert t2.c.a.references(t1.c.a)
        assert not t2.c.a.references(t3.c.a)
        assert not t2.c.a.references(t1.c.b)

    def test_column_references_derived(self):
        t1, t2, t3 = self._single_fixture()
        s1 = tsa.select([tsa.select([t1]).alias()])
        assert t2.c.a.references(s1.c.a)
        assert not t2.c.a.references(s1.c.b)

    def test_copy_doesnt_reference(self):
        t1, t2, t3 = self._single_fixture()
        a2 = t2.c.a.copy()
        assert not a2.references(t1.c.a)
        assert not a2.references(t1.c.b)

    def test_derived_column_references(self):
        t1, t2, t3 = self._single_fixture()
        s1 = tsa.select([tsa.select([t2]).alias()])
        assert s1.c.a.references(t1.c.a)
        assert not s1.c.a.references(t1.c.b)

    def test_invalid_composite_fk_check(self):
        m = MetaData()
        t1 = Table('t1', m, Column('x', Integer), Column('y', Integer),
            ForeignKeyConstraint(['x', 'y'], ['t2.x', 't3.y'])
        )
        t2 = Table('t2', m, Column('x', Integer))
        t3 = Table('t3', m, Column('y', Integer))

        assert_raises_message(
            exc.ArgumentError,
            r"ForeignKeyConstraint on t1\(x, y\) refers to "
                "multiple remote tables: t2 and t3",
            t1.join, t2
        )
        assert_raises_message(
            exc.ArgumentError,
            r"ForeignKeyConstraint on t1\(x, y\) refers to "
                "multiple remote tables: t2 and t3",
            t1.join, t3
        )

        assert_raises_message(
            exc.ArgumentError,
            r"ForeignKeyConstraint on t1\(x, y\) refers to "
                "multiple remote tables: t2 and t3",
            schema.CreateTable(t1).compile
        )

    def test_constraint_copied_to_proxy_ok(self):
        m = MetaData()
        t1 = Table('t1', m, Column('id', Integer, primary_key=True))
        t2 = Table('t2', m, Column('id', Integer, ForeignKey('t1.id'),
                        primary_key=True))

        s = tsa.select([t2])
        t2fk = list(t2.c.id.foreign_keys)[0]
        sfk = list(s.c.id.foreign_keys)[0]

        # the two FKs share the ForeignKeyConstraint
        is_(
            t2fk.constraint,
            sfk.constraint
        )

        # but the ForeignKeyConstraint isn't
        # aware of the select's FK
        eq_(
            t2fk.constraint.elements,
            [t2fk]
        )

class ColumnDefinitionTest(AssertsCompiledSQL, fixtures.TestBase):
    """Test Column() construction."""

    __dialect__ = 'default'

    def columns(self):
        return [Column(Integer),
                 Column('b', Integer),
                 Column(Integer),
                 Column('d', Integer),
                 Column(Integer, name='e'),
                 Column(type_=Integer),
                 Column(Integer()),
                 Column('h', Integer()),
                 Column(type_=Integer())]

    def test_basic(self):
        c = self.columns()

        for i, v in ((0, 'a'), (2, 'c'), (5, 'f'), (6, 'g'), (8, 'i')):
            c[i].name = v
            c[i].key = v
        del i, v

        tbl = Table('table', MetaData(), *c)

        for i, col in enumerate(tbl.c):
            assert col.name == c[i].name

    def test_name_none(self):

        c = Column(Integer)
        assert_raises_message(
            exc.ArgumentError,
            "Column must be constructed with a non-blank name or assign a "
            "non-blank .name ",
            Table, 't', MetaData(), c)

    def test_name_blank(self):

        c = Column('', Integer)
        assert_raises_message(
            exc.ArgumentError,
            "Column must be constructed with a non-blank name or assign a "
            "non-blank .name ",
            Table, 't', MetaData(), c)

    def test_dupe_column(self):
        c = Column('x', Integer)
        Table('t', MetaData(), c)

        assert_raises_message(
            exc.ArgumentError,
            "Column object already assigned to Table 't'",
            Table, 'q', MetaData(), c)

    def test_incomplete_key(self):
        c = Column(Integer)
        assert c.name is None
        assert c.key is None

        c.name = 'named'
        Table('t', MetaData(), c)

        assert c.name == 'named'
        assert c.name == c.key

    def test_bogus(self):
        assert_raises(exc.ArgumentError, Column, 'foo', name='bar')
        assert_raises(exc.ArgumentError, Column, 'foo', Integer,
                          type_=Integer())

    def test_custom_subclass_proxy(self):
        """test proxy generation of a Column subclass, can be compiled."""

        from sqlalchemy.schema import Column
        from sqlalchemy.ext.compiler import compiles
        from sqlalchemy.sql import select

        class MyColumn(Column):
            def _constructor(self, name, type, **kw):
                kw['name'] = name
                return MyColumn(type, **kw)

            def __init__(self, type, **kw):
                Column.__init__(self, type, **kw)

            def my_goofy_thing(self):
                return "hi"

        @compiles(MyColumn)
        def goofy(element, compiler, **kw):
            s = compiler.visit_column(element, **kw)
            return s + "-"

        id = MyColumn(Integer, primary_key=True)
        id.name = 'id'
        name = MyColumn(String)
        name.name = 'name'
        t1 = Table('foo', MetaData(),
            id,
            name
        )

        # goofy thing
        eq_(t1.c.name.my_goofy_thing(), "hi")

        # create proxy
        s = select([t1.select().alias()])

        # proxy has goofy thing
        eq_(s.c.name.my_goofy_thing(), "hi")

        # compile works
        self.assert_compile(
            select([t1.select().alias()]),
            "SELECT anon_1.id-, anon_1.name- FROM "
            "(SELECT foo.id- AS id, foo.name- AS name "
            "FROM foo) AS anon_1",
        )

    def test_custom_subclass_proxy_typeerror(self):
        from sqlalchemy.schema import Column
        from sqlalchemy.sql import select

        class MyColumn(Column):
            def __init__(self, type, **kw):
                Column.__init__(self, type, **kw)

        id = MyColumn(Integer, primary_key=True)
        id.name = 'id'
        name = MyColumn(String)
        name.name = 'name'
        t1 = Table('foo', MetaData(),
            id,
            name
        )
        assert_raises_message(
            TypeError,
            "Could not create a copy of this <class "
            "'test.sql.test_metadata..*MyColumn'> "
            "object.  Ensure the class includes a _constructor()",
            getattr, select([t1.select().alias()]), 'c'
        )

    def test_custom_create(self):
        from sqlalchemy.ext.compiler import compiles, deregister

        @compiles(schema.CreateColumn)
        def compile(element, compiler, **kw):
            column = element.element

            if "special" not in column.info:
                return compiler.visit_create_column(element, **kw)

            text = "%s SPECIAL DIRECTIVE %s" % (
                    column.name,
                    compiler.type_compiler.process(column.type)
                )
            default = compiler.get_column_default_string(column)
            if default is not None:
                text += " DEFAULT " + default

            if not column.nullable:
                text += " NOT NULL"

            if column.constraints:
                text += " ".join(
                            compiler.process(const)
                            for const in column.constraints)
            return text

        t = Table('mytable', MetaData(),
                Column('x', Integer, info={"special": True}, primary_key=True),
                Column('y', String(50)),
                Column('z', String(20), info={"special": True})
            )

        self.assert_compile(
            schema.CreateTable(t),
            "CREATE TABLE mytable (x SPECIAL DIRECTIVE INTEGER "
                "NOT NULL, y VARCHAR(50), "
                "z SPECIAL DIRECTIVE VARCHAR(20), PRIMARY KEY (x))"
        )

        deregister(schema.CreateColumn)

class ColumnDefaultsTest(fixtures.TestBase):
    """test assignment of default fixures to columns"""

    def _fixture(self, *arg, **kw):
        return Column('x', Integer, *arg, **kw)

    def test_server_default_positional(self):
        target = schema.DefaultClause('y')
        c = self._fixture(target)
        assert c.server_default is target
        assert target.column is c

    def test_onupdate_default_not_server_default_one(self):
        target1 = schema.DefaultClause('y')
        target2 = schema.DefaultClause('z')

        c = self._fixture(server_default=target1, server_onupdate=target2)
        eq_(c.server_default.arg, 'y')
        eq_(c.server_onupdate.arg, 'z')

    def test_onupdate_default_not_server_default_two(self):
        target1 = schema.DefaultClause('y', for_update=True)
        target2 = schema.DefaultClause('z', for_update=True)

        c = self._fixture(server_default=target1, server_onupdate=target2)
        eq_(c.server_default.arg, 'y')
        eq_(c.server_onupdate.arg, 'z')

    def test_onupdate_default_not_server_default_three(self):
        target1 = schema.DefaultClause('y', for_update=False)
        target2 = schema.DefaultClause('z', for_update=True)

        c = self._fixture(target1, target2)
        eq_(c.server_default.arg, 'y')
        eq_(c.server_onupdate.arg, 'z')

    def test_onupdate_default_not_server_default_four(self):
        target1 = schema.DefaultClause('y', for_update=False)

        c = self._fixture(server_onupdate=target1)
        is_(c.server_default, None)
        eq_(c.server_onupdate.arg, 'y')

    def test_server_default_keyword_as_schemaitem(self):
        target = schema.DefaultClause('y')
        c = self._fixture(server_default=target)
        assert c.server_default is target
        assert target.column is c

    def test_server_default_keyword_as_clause(self):
        target = 'y'
        c = self._fixture(server_default=target)
        assert c.server_default.arg == target
        assert c.server_default.column is c

    def test_server_default_onupdate_positional(self):
        target = schema.DefaultClause('y', for_update=True)
        c = self._fixture(target)
        assert c.server_onupdate is target
        assert target.column is c

    def test_server_default_onupdate_keyword_as_schemaitem(self):
        target = schema.DefaultClause('y', for_update=True)
        c = self._fixture(server_onupdate=target)
        assert c.server_onupdate is target
        assert target.column is c

    def test_server_default_onupdate_keyword_as_clause(self):
        target = 'y'
        c = self._fixture(server_onupdate=target)
        assert c.server_onupdate.arg == target
        assert c.server_onupdate.column is c

    def test_column_default_positional(self):
        target = schema.ColumnDefault('y')
        c = self._fixture(target)
        assert c.default is target
        assert target.column is c

    def test_column_default_keyword_as_schemaitem(self):
        target = schema.ColumnDefault('y')
        c = self._fixture(default=target)
        assert c.default is target
        assert target.column is c

    def test_column_default_keyword_as_clause(self):
        target = 'y'
        c = self._fixture(default=target)
        assert c.default.arg == target
        assert c.default.column is c

    def test_column_default_onupdate_positional(self):
        target = schema.ColumnDefault('y', for_update=True)
        c = self._fixture(target)
        assert c.onupdate is target
        assert target.column is c

    def test_column_default_onupdate_keyword_as_schemaitem(self):
        target = schema.ColumnDefault('y', for_update=True)
        c = self._fixture(onupdate=target)
        assert c.onupdate is target
        assert target.column is c

    def test_column_default_onupdate_keyword_as_clause(self):
        target = 'y'
        c = self._fixture(onupdate=target)
        assert c.onupdate.arg == target
        assert c.onupdate.column is c

class ColumnOptionsTest(fixtures.TestBase):

    def test_default_generators(self):
        g1, g2 = Sequence('foo_id_seq'), ColumnDefault('f5')
        assert Column(String, default=g1).default is g1
        assert Column(String, onupdate=g1).onupdate is g1
        assert Column(String, default=g2).default is g2
        assert Column(String, onupdate=g2).onupdate is g2

    def test_type_required(self):
        assert_raises(exc.ArgumentError, Column)
        assert_raises(exc.ArgumentError, Column, "foo")
        assert_raises(exc.ArgumentError, Column, default="foo")
        assert_raises(exc.ArgumentError, Column, Sequence("a"))
        assert_raises(exc.ArgumentError, Column, "foo", default="foo")
        assert_raises(exc.ArgumentError, Column, "foo", Sequence("a"))
        Column(ForeignKey('bar.id'))
        Column("foo", ForeignKey('bar.id'))
        Column(ForeignKey('bar.id'), default="foo")
        Column(ForeignKey('bar.id'), Sequence("a"))
        Column("foo", ForeignKey('bar.id'), default="foo")
        Column("foo", ForeignKey('bar.id'), Sequence("a"))

    def test_column_info(self):

        c1 = Column('foo', String, info={'x': 'y'})
        c2 = Column('bar', String, info={})
        c3 = Column('bat', String)
        assert c1.info == {'x': 'y'}
        assert c2.info == {}
        assert c3.info == {}

        for c in (c1, c2, c3):
            c.info['bar'] = 'zip'
            assert c.info['bar'] == 'zip'

class CatchAllEventsTest(fixtures.TestBase):

    def teardown(self):
        events.SchemaEventTarget.dispatch._clear()

    def test_all_events(self):
        canary = []
        def before_attach(obj, parent):
            canary.append("%s->%s" % (obj.__class__.__name__,
                                parent.__class__.__name__))

        def after_attach(obj, parent):
            canary.append("%s->%s" % (obj.__class__.__name__, parent))

        event.listen(schema.SchemaItem, "before_parent_attach", before_attach)
        event.listen(schema.SchemaItem, "after_parent_attach", after_attach)

        m = MetaData()
        Table('t1', m,
            Column('id', Integer, Sequence('foo_id'), primary_key=True),
            Column('bar', String, ForeignKey('t2.id'))
        )
        Table('t2', m,
            Column('id', Integer, primary_key=True),
        )

        eq_(
            canary,
            ['Sequence->Column', 'Sequence->id', 'ForeignKey->Column',
             'ForeignKey->bar', 'Table->MetaData',
             'PrimaryKeyConstraint->Table', 'PrimaryKeyConstraint->t1',
             'Column->Table', 'Column->t1', 'Column->Table',
             'Column->t1', 'ForeignKeyConstraint->Table',
             'ForeignKeyConstraint->t1', 'Table->MetaData(bind=None)',
             'Table->MetaData', 'PrimaryKeyConstraint->Table',
             'PrimaryKeyConstraint->t2', 'Column->Table', 'Column->t2',
             'Table->MetaData(bind=None)']
        )

    def test_events_per_constraint(self):
        canary = []

        def evt(target):
            def before_attach(obj, parent):
                canary.append("%s->%s" % (target.__name__,
                                        parent.__class__.__name__))

            def after_attach(obj, parent):
                canary.append("%s->%s" % (target.__name__, parent))
            event.listen(target, "before_parent_attach", before_attach)
            event.listen(target, "after_parent_attach", after_attach)

        for target in [
            schema.ForeignKeyConstraint, schema.PrimaryKeyConstraint,
            schema.UniqueConstraint,
            schema.CheckConstraint
        ]:
            evt(target)

        m = MetaData()
        Table('t1', m,
            Column('id', Integer, Sequence('foo_id'), primary_key=True),
            Column('bar', String, ForeignKey('t2.id')),
            Column('bat', Integer, unique=True),
        )
        Table('t2', m,
            Column('id', Integer, primary_key=True),
            Column('bar', Integer),
            Column('bat', Integer),
            CheckConstraint("bar>5"),
            UniqueConstraint('bar', 'bat')
        )
        eq_(
            canary,
            [
                'PrimaryKeyConstraint->Table', 'PrimaryKeyConstraint->t1',
                'ForeignKeyConstraint->Table', 'ForeignKeyConstraint->t1',
                'UniqueConstraint->Table', 'UniqueConstraint->t1',
                'PrimaryKeyConstraint->Table', 'PrimaryKeyConstraint->t2',
                'CheckConstraint->Table', 'CheckConstraint->t2',
                'UniqueConstraint->Table', 'UniqueConstraint->t2'
            ]
        )


import hashlib
import base64
import random
import sys
import time
from coincurve.keys import PrivateKey
from coincurve._libsecp256k1 import ffi

class TU(object):  # Transaction Utilities
    @classmethod
    def hash(cls, message):
        return hashlib.sha256(message.encode("utf-8")).digest().hex()

    @classmethod
    def generate_deterministic_signature(cls, config, message: str, private_key=None):
        if not private_key:
            private_key = config.private_key
        key = PrivateKey.from_hex(private_key)
        signature = key.sign(message.encode("utf-8"))
        return base64.b64encode(signature).decode("utf-8")

    @classmethod
    def generate_signature_with_private_key(cls, private_key, message):
        x = ffi.new("long long *")
        x[0] = random.SystemRandom().randint(0, sys.maxsize)
        key = PrivateKey.from_hex(private_key)
        signature = key.sign(message.encode("utf-8"), custom_nonce=(ffi.NULL, x))
        return base64.b64encode(signature).decode("utf-8")

    @classmethod
    def generate_signature(cls, message, private_key):
        x = ffi.new("long long *")
        x[0] = random.SystemRandom().randint(0, sys.maxsize)
        key = PrivateKey.from_hex(private_key)
        signature = key.sign(message.encode("utf-8"), custom_nonce=(ffi.NULL, x))
        return base64.b64encode(signature).decode("utf-8")

    @classmethod
    def generate_rid(cls, config, username_signature):
        username_signatures = sorted(
            [str(config.username_signature), str(username_signature)], key=str.lower
        )
        return (
            hashlib.sha256(
                (str(username_signatures[0]) + str(username_signatures[1])).encode(
                    "utf-8"
                )
            )
            .digest()
            .hex()
        )

    @classmethod
    async def send(
        cls,
        config,
        to,
        value,
        from_address=True,
        inputs=None,
        dry_run=False,
        exact_match=False,
        outputs=None,
    ):
        from yadacoin.core.transaction import NotEnoughMoneyException, Transaction

        if from_address == config.address:
            public_key = config.public_key
            private_key = config.private_key
        else:
            child_key = await config.mongo.async_db.child_keys.find_one(
                {"address": from_address}
            )
            if child_key:
                public_key = child_key["public_key"]
                private_key = child_key["private_key"]
            else:
                return {"status": "error", "message": "no wallet matching from address"}

        if outputs:
            for output in outputs:
                output["value"] = float(output["value"])
        else:
            outputs = [{"to": to, "value": value}]

        if not inputs:
            inputs = []

        try:
            transaction = await Transaction.generate(
                fee=0.00,
                public_key=public_key,
                private_key=private_key,
                inputs=inputs,
                outputs=outputs,
                exact_match=exact_match,
            )
        except NotEnoughMoneyException:
            return {"status": "error", "message": "not enough money"}
        except:
            raise
        try:
            await transaction.verify()
        except:
            return {"error": "invalid transaction"}

        if not dry_run:
            await config.mongo.async_db.miner_transactions.insert_one(
                transaction.to_dict()
            )
            async for peer_stream in config.peer.get_sync_peers():
                await config.nodeShared.write_params(
                    peer_stream, "newtxn", {"transaction": transaction.to_dict()}
                )
                if peer_stream.peer.protocol_version > 1:
                    config.nodeClient.retry_messages[
                        (
                            peer_stream.peer.rid,
                            "newtxn",
                            transaction.transaction_signature,
                        )
                    ] = {"transaction": transaction.to_dict()}
        return transaction.to_dict()

    @classmethod
    async def clean_mempool(cls, config):
        if not hasattr(config, "last_mempool_clean"):
            config.last_mempool_clean = 0

        to_delete = []
        txns_to_clean = config.mongo.async_db.miner_transactions.find(
            {"time": {"$gte": config.last_mempool_clean}}
        )
        async for txn_to_clean in txns_to_clean:
            for x in txn_to_clean.get("inputs"):
                if await config.BU.is_input_spent(x["id"], txn_to_clean["public_key"]):
                    to_delete.append(
                        {
                            "reason": "MempoolCleaner: Input already spent",
                            "txn": txn_to_clean,
                        }
                    )
                    continue
            if await config.mongo.async_db.blocks.find_one(
                {"transactions.id": txn_to_clean["id"]}
            ):
                to_delete.append(
                    {
                        "reason": "MempoolCleaner: Transaction already in blockchain",
                        "txn": txn_to_clean,
                    }
                )

        txns_to_clean = config.mongo.async_db.miner_transactions.find(
            {"time": {"$lte": time.time() - 60 * 60}, "never_expire": {"$ne": True}}
        )
        async for txn_to_clean in txns_to_clean:
            to_delete.append(
                {"reason": "MempoolCleaner: Transaction expired", "txn": txn_to_clean}
            )

        for txn in to_delete:
            await config.mongo.async_db.failed_transactions.insert_one(txn)
            await config.mongo.async_db.miner_transactions.delete_many(
                {"id": txn["txn"]["id"]}
            )

        config.last_mempool_clean = time.time()

    @classmethod
    async def rebroadcast_mempool(cls, config, include_zero=False):
        from yadacoin.core.transaction import Transaction

        query = {"outputs.value": {"$gt": 0}}
        if include_zero:
            query = {}

        async for txn in config.mongo.async_db.miner_transactions.find(query):
            x = Transaction.from_dict(txn)
            async for peer_stream in config.peer.get_sync_peers():
                await config.nodeShared.write_params(
                    peer_stream, "newtxn", {"transaction": x.to_dict()}
                )
                if peer_stream.peer.protocol_version > 1:
                    config.nodeClient.retry_messages[
                        (peer_stream.peer.rid, "newtxn", x.transaction_signature)
                    ] = {"transaction": x.to_dict()}
                time.sleep(0.1)

    @classmethod
    async def rebroadcast_failed(cls, config, id):
        from yadacoin.core.transaction import Transaction

        async for txn in config.mongo.async_db.failed_transactions.find(
            {"txn.id": id.replace(" ", "+")}
        ):
            x = Transaction.from_dict(txn["txn"])
            async for peer_stream in config.peer.get_sync_peers():
                await config.nodeShared.write_params(
                    peer_stream, "newtxn", {"transaction": x.to_dict()}
                )
                if peer_stream.peer.protocol_version > 1:
                    config.nodeClient.retry_messages[
                        (peer_stream.peer.rid, "newtxn", x.transaction_signature)
                    ] = {"transaction": x.to_dict()}
                time.sleep(0.1)

    @classmethod
    async def get_current_smart_contract_txns(cls, config, start_index):
        return config.mongo.async_db.blocks.aggregate(
            [
                {
                    "$match": {
                        "transactions": {
                            "$elemMatch": {
                                "relationship.smart_contract.expiry": {
                                    "$gt": start_index
                                }
                            }
                        }
                    }
                },
                {"$unwind": "$transactions"},
                {
                    "$match": {
                        "transactions.relationship.smart_contract.expiry": {
                            "$gt": start_index
                        }
                    }
                },
                {"$sort": {"transactions.time": 1}},
            ]
        )

    @classmethod
    async def get_expired_smart_contract_txns(cls, config, start_index):
        return config.mongo.async_db.blocks.aggregate(
            [
                {
                    "$match": {
                        "transactions.relationship.smart_contract.expiry": start_index
                    }
                },
                {"$unwind": "$transactions"},
                {
                    "$match": {
                        "transactions.relationship.smart_contract.expiry": start_index
                    }
                },
                {"$sort": {"index": 1, "transactions.time": 1}},
            ]
        )

    @classmethod
    async def get_trigger_txns(
        cls, config, smart_contract_txn, start_index=None, end_index=None
    ):
        match = {
            "transactions": {
                "$elemMatch": {"relationship.smart_contract": {"$exists": False}}
            },
            "transactions.requested_rid": smart_contract_txn.requested_rid,
            "transactions": {
                "$elemMatch": {
                    "public_key": {
                        "$ne": smart_contract_txn.relationship.identity.public_key
                    }
                }
            },
        }
        if start_index and end_index:
            match["index"]["$gte"] = start_index
            match["index"]["$lt"] = end_index
        match2 = {
            "transactions.relationship.smart_contract": {"$exists": False},
            "transactions.requested_rid": smart_contract_txn.requested_rid,
            "transactions.public_key": {
                "$ne": smart_contract_txn.relationship.identity.public_key
            },
        }
        trigger_txn_blocks = config.mongo.async_db.blocks.aggregate(
            [
                {"$match": match},
                {"$unwind": "$transactions"},
                {"$match": match2},
                {"$sort": {"transactions.fee": -1, "transactions.time": 1}},
            ]
        )
        async for x in trigger_txn_blocks:
            yield x

    @classmethod
    def get_transaction_objs_list(cls, transaction_objs):
        return [y for x in list(transaction_objs.values()) for y in x]


from kivy.properties import (
    NumericProperty,
    ObjectProperty,
    BooleanProperty,
    AliasProperty,
)
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.behaviors import ButtonBehavior

class PlayerSelector(BoxLayout):
    gameObject = ObjectProperty()
    numPlayers = NumericProperty(2)
    numAI = NumericProperty(1)
    minPlayers = NumericProperty(1)
    maxPlayers = NumericProperty(2)
    maxAI = NumericProperty(1)
    hasAI = BooleanProperty()

    numPlayersText = AliasProperty(
        lambda self: f"Number of players: {self.numPlayers:.0f}", bind=["numPlayers"]
    )
    numAIText = AliasProperty(
        lambda self: f"Number of AIs: {self.numAI:.0f}", bind=["numAI"]
    )

    def __init__(self, **kwargs):
        BoxLayout.__init__(self, **kwargs)
        self.register_event_type("on_choose")

    def on_gameObject(self, instance, gameObject):
        self.minPlayers = gameObject.minPlayers
        self.maxPlayers = gameObject.maxPlayers
        self.numPlayers = gameObject.maxPlayers
        self.hasAI = gameObject.hasAI
        if self.hasAI:
            self.maxAI = self.maxPlayers - 1
            self.numAI = self.maxPlayers - 1

    def submit(self):
        players = []
        numAI = self.numAI if self.hasAI else 0
        players += [False] * int(self.numPlayers - numAI)
        players += [True] * int(numAI)
        self.dispatch("on_choose", tuple(players))

    def on_choose(self, players):
        pass


import shutil
import warnings
from typing import Tuple
import numpy as np
import cv2

from PIL import Image
from config import *
from img_proc_util import *
##  sklearn image related functions

import skimage.color
import skimage.io
import skimage.metrics
from skimage import img_as_ubyte
## importing torch and torchvision utilities
import torch
import torchvision.utils

def image_quality_assessment(sr_path: str, hr_path: str) -> Tuple[float, float, float]:

    ## reading hr and sr image
    hr_image = skimage.io.imread(hr_path)
    sr_image = skimage.io.imread(sr_path)

    if sr_image.shape[1] != sr_image.shape[0]:
        warnings.warn("Image shape - height and width not equal")
    if hr_image.shape != sr_image.shape:
        warnings.warn("spectrum calculation error")

    spectrum = cal_spectrum(sr_image, hr_image)
    ## calculation of PSNR and SSIM
    psnr, ssim = cal_psnr_and_ssim(sr_image, hr_image)

    return psnr, ssim, spectrum

def cal_spectrum(sr_image, hr_image) -> float:

    sr_temp = img_as_ubyte(sr_image)
    hr_temp = img_as_ubyte(hr_image)
    sr = cv2.cvtColor(sr_temp, cv2.COLOR_RGB2GRAY)
    hr = cv2.cvtColor(hr_temp, cv2.COLOR_RGB2GRAY)

    sr_shape = sr.shape[0]
    total_hist_sr = []
    total_hist_hr = []
    for hist_height in range(sr_shape):

        hist_sr = cv2.calcHist([sr[hist_height, :]], [0], None, [sr_shape], [0, 255])
        hist_hr = cv2.calcHist([hr[hist_height, :]], [0], None, [sr_shape], [0, 255])
        total_hist_sr.append(hist_sr)
        total_hist_hr.append(hist_hr)

    total_spectrum_sr = []
    total_spectrum_hr = []
    for idx in range(sr_shape):

        fft_sr = np.fft.fft(total_hist_sr[idx])
        fft_hr = np.fft.fft(total_hist_hr[idx])

        spectrum_sr = np.abs(fft_sr)
        spectrum_hr = np.abs(fft_hr)

        spectrum_sr = spectrum_sr[range(sr_shape // 2)]
        spectrum_hr = spectrum_hr[range(sr_shape // 2)]
        total_spectrum_sr.append(spectrum_sr)
        total_spectrum_hr.append(spectrum_hr)

    average_spectrum_sr = []
    average_spectrum_hr = []
    diff = 0.
    for spectrum_val in range(sr_shape // 2):
        total_spectrum_sr = 0
        total_spectrum_hr = 0
        for idx in range(sr_shape):
            total_spectrum_sr += total_spectrum_sr[idx][spectrum_val]
            total_spectrum_hr += total_spectrum_hr[idx][spectrum_val]
        average_spectrum_sr.append(total_spectrum_sr / sr_shape)
        average_spectrum_hr.append(total_spectrum_hr / sr_shape)

    for index in range(sr_shape // 2):
        diff += (average_spectrum_hr[index] - average_spectrum_sr[index]) ** 2

    spectrum_val = float(np.sqrt(diff / (sr_shape / 2)))

    return spectrum_val

def cal_psnr_and_ssim(sr_image, hr_image) -> Tuple[float, float]:
    ## calculate psnr and ssim

    sr_temp = normalize(sr_image)
    hr_temp = normalize(hr_image)

    sr_temp = skimage.color.rgb2ycbcr(sr_temp)[:, :, 0:1]
    hr_temp = skimage.color.rgb2ycbcr(hr_temp)[:, :, 0:1]

    sr = normalize(sr_temp)
    hr = normalize(hr_temp)
    ssim = skimage.metrics.structural_similarity(sr,
                                                 hr,
                                                 win_size=11,
                                                 gaussian_weights=True,
                                                 multichannel=True,
                                                 data_range=1.0,
                                                 K1=0.01,
                                                 K2=0.03,
                                                 sigma=1.5)
    psnr = skimage.metrics.peak_signal_noise_ratio(sr, hr, data_range=1.0)

    return psnr, ssim

def main() -> None:
    ## defining the main function to get the functions in line

    if os.path.exists(exp_dir):
        shutil.rmtree(exp_dir)
    os.makedirs(exp_dir)

    ## load models to evaluate
    state_dict = torch.load(model_path, map_location=device)
    model.load_state_dict(state_dict)

    model.eval()

    model.half()

    total_spectrum_val = 0.0
    total_ssim_val = 0.0
    total_psnr_val = 0.0

    filenames = os.listdir(lr_dir)

    total_files = len(filenames)

    for index in range(total_files):
        lr_path = os.path.join(lr_dir, filenames[index])
        sr_path = os.path.join(sr_dir, filenames[index])
        hr_path = os.path.join(hr_dir, filenames[index])

        lr_image = Image.open(lr_path)
        lr_tensor = image2tensor(lr_image).to(device).unsqueeze(0)
        lr_tensor = lr_tensor.half()
        with torch.no_grad():
            sr_tensor = model(lr_tensor)
            torchvision.utils.save_image(sr_tensor, sr_path)

        print(f"Processing `{os.path.abspath(lr_path)}`...")
        psnr, ssim, spectrum = image_quality_assessment(sr_path, hr_path)
        total_spectrum_val += spectrum

        total_ssim_val += ssim
        total_psnr_val += psnr

    print(f"PSNR:     {total_psnr_val / total_files:.2f}.\n"
          f"SSIM:     {total_ssim_val / total_files:.4f}.\n"
          f"Spectrum: {total_spectrum_val / total_files:.6f}.\n")

if __name__ == "__main__":
    main()


import os
import json
import boto3
from boto3.session import Session
#import openpyxl
from botocore.exceptions import ClientError
import datetime
import logging
#import pytz
#import tzlocal
import dateutil.parser
from pprint import pprint
###
#--- [ref] change region programmatically
#https://russell.ballestrini.net/setting-region-programmatically-in-boto3/

#????

#--- RESOURCES AND CLIENTS ---------
#====================================
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
s3Resource = boto3.resource('s3')
#bclient = boto3.client('ce')
athena_client = boto3.client('athena')
budgets_client = boto3.client('budgets')
dynamodb = boto3.resource('dynamodb')
ec2_client = boto3.client('ec2')
rsclient = boto3.client('redshift')
iamc = boto3.client('iam')

reg_arr = []
count = 0

#=====================================
"""
https://www.decalage.info/en/python/print_list

"""

#aws_acct_num = boto3.client('sts').get_caller_identity()['Account']

#-- EVENTS RULE REFERENCE
"""https://github.com/lroguet/amzn-cloudformation/blob/master/lambda/scheduled-lambda.yml
"""

#-- ATTACH IAM POLICY TO A ROLE
"""
response = client.attach_role_policy(
    RoleName='string',
    PolicyArn='string'
)

"""

#--- LIST ALL IAM USERS FOR AN ACCOUNT
"""
for user in iamc.list_users()['Users']:
  user_name = user['UserName']
  print(user_name)
"""
#--- PRINT ALL IAM ACCESS KEYS FOR USERS WHO HAVE ONE OR MORE
"""
  keys = iamc.list_access_keys(UserName=user)
  #print(keys)
  for b in keys['AccessKeyMetadata']:
      username = b['UserName']
      accesskeyid = b['AccessKeyId']
      status = b['Status']
      createdate = str(b['CreateDate']) # creation date
      print("{0:<20} {1:<25} {2:<15} {3:<10}".format(username, accesskeyid, status, createdate))
      #access_key = iam.AccessKey(username,accesskeyid)
        #access_key.deactivate()
"""

#--- PRINT ALL SSH KEYS FOR USERS WHO HAVE ONE OR MORE
"""
iamc = boto3.client('iam')
iamr = boto3.resource('iam')
x=0
for user in iamc.list_users()['Users']:

  user_name = user['UserName']
 #['SSHPublicKeys']
 #['ResponseMetaData']
  try:
    response = iamc.list_ssh_public_keys(UserName=user_name)
    for item in response.values():
      #print(user_name) # prints all users
      num_items = len(item)
      if num_items >= 1:
        for each in item:
          print(each['SSHPublicKeyId']) # prints users  and the keys of thosewho have ssh keys
    x = x + 1
  except:
    continue
"""
#--- REPORT CLASS
"""
class Report:
  def __init__(aws_acct_num, creation_date,rsrc_type,rsrc_name,owner):
    self.aws_acct_num = aws_acct_num
    slef.reation_date = reation_date
    self.rsrc_type = rsrc_type
    self.rsrc_name = rsrc_name
    self.owner = owner

  def write_report(aws_acct_num, creation_date,rsrc_type,rsrc_name,owner):
    wb = openpyxl.load_workbook('inventory.xlsx')
    wb.sheetnames
    sheet = wb.active
    currSheet = sheet.title

    sheet.append((aws_acct_num,readable_date,"s3",bucket['Name'], bucket_owner))
    print("mark")
    wb.save('inventory.xlsx')
"""
#--- CREATE CLOUDWATCH CLIENT
"""
regions = [region['RegionName'] for region in ec2_client.describe_regions()['Regions']]

for region in regions:
  print(region)
  bclient = boto3.client('redshift', region_name = region)
  cluster_list = response = bclient.describe_cluster_parameters(
  ParameterGroupName = 'default',
  )
  for cluster in cluster_list:
    pprint(cluster)
"""

#--- GET AWS ACCOUNT NUMBER
"""
boto3.client('sts').get_caller_identity()['Account']
def lambda_handler(event, context):
  print("My account ID is %s" % get_account_id(context))

"""

#--- COMPARING DATES IN PYTHON

time=[]
dt = datetime.datetime.now()
time1 = datetime.datetime(2019, 11, 1)
time2 = datetime.datetime(2020, 3, 30)
time.append(time1)
time.append(time2)
print(time1)
print(time2)
print(time2 - (datetime.timedelta(30)))
past_thirty = time2 - (datetime.timedelta(30))

for x in time:

  if(x <= time2 and x >= past_thirty):
    print(str(x) + " this time is in range")
  else:
    print(str(x) + " this time not in range")

#--- RETRIEVE S3 BUCKET POLICY
"""
result = s3.get_bucket_policy(Bucket='74481-wfm-eidin-flq-explore-sbx-logging')
print(result['Policy'])
"""
#--- CLOUDFORMATION
"""
cfn.list_stacks()
print(type(cfn))
"""

#--- LIST ALL STACKS IN AN ACCOUNT
"""
regions = [region['RegionName'] for region in ec2_client.describe_regions()['Regions']]
count = 1
for region in regions:
  reg_arr.append(region)
  cfn = boto3.client('cloudformation', region_name = region)
  for stack in cfn.list_stacks(
    StackStatusFilter = [
    'CREATE_COMPLETE', 'UPDATE_COMPLETE'
    ])['StackSummaries']:
      #print('{0}:{1}'.format(stack['StackName'], stack['StackId']))
      count += 1
      print(stack['StackName'])
      #print(stack['StackId'])
      continue
print("here's the count: " + str(count))

#for reg in reg_arr:
  #print(reg)

"""

#--- LIST ALL REGIONS
"""
ec2_client = boto3.client('ec2')
regions = [region['RegionName'] for region in ec2_client.describe_regions()['Regions']]
for region in regions:
  reg_arr.append(region)

for region in reg_arr:
  print(region)
#regions = ec2_client.describe_regions().get('Regions',[] )
#print(reg_arr)
"""

#--- PRINT ALL REGIONS THAT ARE ACTIVE
"""
for region in regions:
  reg_arr.append(region)
  continue
"""

#--- PRINT THE NUMBER OF BUCKETS
"""
print("lot's of buckets here guys:"+str(len(response['Buckets'])))
"""

#--- CREATE AN S3 BUCKET POLICY
"""
bucket_name = 'BUCKET_NAME'
bucket_policy = {
    'Version': '2012-10-17',
    'Statement': [{
        'Sid': 'AddPerm',
        'Effect': 'Allow',
        'Principal': '*',
        'Action': ['s3:GetObject'],
        'Resource': f'arn:aws:s3:::{bucket_name}/*'
    }]
}

#--- Convert the policy from JSON dict to string
bucket_policy = json.dumps(bucket_policy)

# Set the new policy
s3 = boto3.client('s3')
s3.put_bucket_policy(Bucket=bucket_name, Policy=bucket_policy)

"""

#--- GET S3 BUCKET TAGS
"""
s3 = boto3.client('s3')
buckets = s3_client.list_buckets()
s3r = boto3.resource('s3')

response_c = s3.list_buckets()
buckets = response_c
for bucket in response_c['Buckets']:
  try:
    #print(bucket['Name'])
    raw_date = bucket['CreationDate']
    readable_date = raw_date.strftime("%m-%d-%Y")
    time_today = datetime.datetime.now()
    past_thirty = time_today - (datetime.timedelta(30))
    bucket_tag = s3.get_bucket_tagging(Bucket = bucket['Name'])
    bucket_owner_tag = bucket_tag['TagSet'][0]['Key']
    if(bucket_owner_tag == 'owner'):
      print(bucket_tag['TagSet'][0]['Value'])
    else:
      continue
  except:
    continue
  #print("Bucket Name: " + bucket['Name']+ " -- Creation Date: " + readable_date)

[COMMENT]
for bucket in buckets:
  try:
      print(bucket)
      response = s3_client.get_bucket_tagging(Bucket=bucket)
      print(response['owner'])
      #tagset = response['TagSet']
  except ClientError:
      print(bucket, "does not have tags, adding tags")
[END_COMMENT]

"""

#--- S3 - LIST BUCKET NAMES AND CREATION DATES -- https://www.w3schools.com/python/python_datetime.asp
"""

s3 = boto3.client('s3')
buckets = s3_client.list_buckets()
s3r = boto3.resource('s3')
aws_acct_num = boto3.client('sts').get_caller_identity()['Account']
wb = openpyxl.load_workbook('inventory.xlsx')
wb.sheetnames
sheet = wb.active
currSheet = sheet.title
response_c = s3_client.list_buckets()
buckets = response_c
for bucket in response_c['Buckets']:
  try:
    raw_date = bucket['CreationDate']
    readable_date = raw_date.strftime("%m-%d-%Y")
    time_today = datetime.datetime.now()
    past_thirty = time_today - (datetime.timedelta(30))
    bucket_tag = s3.get_bucket_tagging(Bucket = bucket['Name'])
    bucket_owner_tag = bucket_tag['TagSet'][0]['Key']

    if(raw_date.date() >= past_thirty.date()):
      bucket_tagging = s3r.get_bucket_tagging(Bucket = bucket['Name'])
      bucket_owner_tag = bucket_tag['TagSet'][0]['Key']
      #print(bucket['Name'])
      print(bucket_owner_tag)
    if(bucket_owner_tag == 'owner'):
      bucket_owner = bucket_tag['TagSet'][0]['Value']
      print(bucket_owner)
    else:
      bucket_owner = "no tag found"
      continue

    sheet.append((aws_acct_num,readable_date,"s3",bucket['Name'], bucket_owner))
    #print(bucket)
    #sheet.append(B,[readable_date])
    #print(raw_date.strftime("%x"))
    #print(bucket)
    #print(bucket['CreationDate'])

    wb.save('inventory.xlsx')
  except:
    continue
"""

#--- S3 LOGGING INFO
"""
bucket_logging = s3Resource.BucketLogging('74481-jeffs-test-land')
print(bucket_logging)
"""
#--- s3 ACL
"""
s3ACL = s3.get_bucket_acl('2120950-land')
s3ACL = s3.acl('2120950-land')
print(s3ACL)

"""
#--- OPEN OPENPYXL
""""
wb = openpyxl.load_workbook('inventory.xlsx')
wb.sheetnames
sheet = wb.active
currSheet = sheet.title

names=[]

for bucket in response['Buckets']:
  try:
    bucket_tagging = s3.get_bucket_tagging(Bucket = bucket['Name'])
    #print(bucket['Name'])
    #print(bucket_tagging)
    sheet.append([bucket['Name']])

    #print(get_s3_keys(bucket['Name']))
  except:
    continue
    #print("XXX")

names.append(names)
wb.save(filename='/mnt/c/Users/jjone/Downloads/sbx_python_boto/inventory.xlsx')
#wb.save()
"""

"""
print(type(sheet))

for row in sheet.values:
  for value in row:
    print(value)

print(currSheet)
"""

"""
x = 1
#print(f'  {bucket["Name"]}')

workbook = Workbook()
sheet = workbook.active
for bucket in response['Buckets']:

  print(sheet["A"+str(x)])

  x+=x

workbook.save(filename="./inventory.xlsx")
LANDING_BUCKET_NAME = os.environ['LANDING_BUCKET_NAME']
PERSIST_BUCKET_NAME = os.environ['PERSIST_BUCKET_NAME']
SNS = os.environ['SNS']

this will get all the regions that dynamoDB is available in

s = Session()
dynamodb_regions = s.get_available_regions('dynamodb')
for dynamo_region in dynamodb_regions:
  print(dynamo_region)

"""

#---- GET A LIST OF ALL TOPIC ARNS FROM THE RESPONSE
"""
topics = [topic['TopicArn'] for topic in response['Topics']]

 Print out the topic list
print("Topic List: %s" % topics)
snstopic = 'arn:aws:sns:us-east-1:744810512381:NotifyJeff'
if snstopic in topics:
    #print("we found your topic")
"""

"""
    # log event and context attributes
    print(json.dumps(event, default=str, indent=4))
    print(json.dumps(context.__dict__, default=str, indent=4))

    # get bucket name and object key attributes from event object

    source_bucket_name = event['Records'][0]['s3']['bucket']['name']

    source_object_key = urllib.parse.unquote(event['Records'][0]['s3']['object']['key'])
    print(f"{source_object_key} PUT to {source_bucket_name}")
"""
"""
    f = open("/tmp/jeffstest.txt", "a")
    for x in event:
        print(x)
        f.write(x)
    f.close()
    s3.Object('jeffs-test-land-copy1', 'jeffstest.txt').put(Body=open('/tmp/jeffstest.txt', 'rb'))
    #s3.upload_fileobj(f, "jeffs-test-land-main", "somefile")
"""
"""
    if not source_bucket_name == LANDING_BUCKET_NAME:
        raise EnvironmentError("event source_bucket_name NOT equals environment LANDING_BUCKET_NAME")

    # build copy source and target object instance from event object attributes
    copy_source = {'Bucket': source_bucket_name, 'Key': source_object_key}
    target_obj = s3.Object(PERSIST_BUCKET_NAME, source_object_key)

    print(f"{source_object_key} COPY to {PERSIST_BUCKET_NAME}")
    target_obj.copy_from(CopySource=copy_source)

    print(f"wait for {source_object_key} to exist in {PERSIST_BUCKET_NAME}")
    target_obj.wait_until_exists()

    print(f"{source_object_key} COPY to {PERSIST_BUCKET_NAME} successful")
"""
#--- scrap
"""
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
s3r = s3_client.list_buckets()
buckets = s3r
for bucket in s3r['Buckets']:

  bucket_tagging = s3r.BucketTagging(Bucket = bucket['Name'])
  #print(bucket['Name'])
  print(bucket_tagging)
  #sheet.append([bucket['Name']])

    #print(get_s3_keys(bucket['Name']))
"""


from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Sequence, Func, Wait
from direct.task import Task
from direct.gui.DirectGui import *

from panda3d.core import *

from math import *

class Play(DirectObject):
    def __init__(self):
        # Load the environment model
        self.parentNode = render.attachNewNode('BattleMode')
        self.scene = loader.loadModel("tp/models/environment")
        self.scene.reparentTo(self.parentNode)

        # Load the actor
        base.currPlayer.actor.reparentTo(self.parentNode)
        base.currPlayer.actor.setPos(0, 0, 0)
        base.currPlayer.actor.pose('btwist', 1)

        # define controls
        self.accept('shift-u', base.currPlayer.tryTrick, [base.currPlayer.gainer, taskMgr])
        self.accept('shift-i', base.currPlayer.tryTrick, [base.currPlayer.gswitch, taskMgr])
        self.accept('shift-o', base.currPlayer.tryTrick, [base.currPlayer.cork, taskMgr])
        self.accept('shift-p', base.currPlayer.tryTrick, [base.currPlayer.doublecork, taskMgr])

        self.accept('control-u', base.currPlayer.tryTrick, [base.currPlayer.fiveForty, taskMgr])
        self.accept('control-i', base.currPlayer.tryTrick, [base.currPlayer.btwist, taskMgr])
        self.accept('control-o', base.currPlayer.tryTrick, [base.currPlayer.raiz, taskMgr])
        # self.accept('control-p', base.currPlayer.tryTrick, [base.currPlayer.cartFull])

        # Add SetCameraTask to task manager
        # IMPORTANT: camera is parented to the dummyNode in tricker's chest
        self.trickerDummyNode = self.parentNode.attach_new_node("trickerDummyNode")
        self.trickerDummyNode.reparentTo(self.parentNode)
        self.trickerDummyNode.setPos(base.currPlayer.actor, (0, 0, 3))

        camera.reparentTo(self.parentNode)

        camera.setPos(0, -20, 10)
        camera.lookAt(self.trickerDummyNode)

        taskMgr.add(self.FollowCamTask, "follow")

        # Lights
        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.5, 0.5, 0.5, 1))
        alnp = self.parentNode.attachNewNode(alight)
        self.parentNode.setLight(alnp)

        plight = PointLight('plight')
        plight.setColor(VBase4(1, 1, 1, 1))
        plnp = self.parentNode.attachNewNode(plight)
        plnp.setPos(20, 0, 20)
        self.parentNode.setLight(plnp)

        self.uiDrawer = MeshDrawer2D()
        self.uiDrawer.setBudget(10)
        self.uiDrawerNode = self.uiDrawer.getRoot()
        self.uiDrawerNode.reparentTo(base.a2dBottomCenter)

        self.gradeText = OnscreenText(pos=(-0.4, -0.3), scale=0.3,
                                      parent=base.a2dTopRight)
        self.timingText = OnscreenText(pos=(-0.5, -0.5), scale=0.075,
                                       parent=base.a2dTopRight, fg=(1, 1, 1, 1))
        self.scoreText = OnscreenText(pos=(0.3, -0.3), scale=0.1,
                                      parent=base.a2dTopLeft, fg=(1, 1, 1, 1))
        self.comboText = OnscreenText(pos=(0.3, -0.2), scale=0.1,
                                      parent=base.a2dTopLeft, fg=(1, 1, 1, 1))
        self.nameText = OnscreenText(text=base.currPlayer.getName(),
                                     pos=(0, -0.2), scale=0.2,
                                     parent=base.a2dTopCenter, fg=(1, 1, 1, 1))
        self.stamBarText = OnscreenText(text="stamina", scale=0.075,
                                        parent=base.a2dBottomCenter, pos=(-0.6,0.09),
                                        fg=(1,1,1,1))
        self.timeBarText = OnscreenText(text="timing", scale=0.075,
                                        parent=base.a2dBottomCenter, pos=(-0.625, 0.375),
                                        fg=(1, 1, 1, 1))

        self.startMenuButton = DirectButton(text=("quit"), scale=0.075,
                                            command=self.switchToMainMenu, parent=base.a2dTopLeft,
                                            pos=(0.075, 0, -0.07))

        self.initialDialog = None
        self.popupText = None
        self.popupSeq = None

    def switchToMainMenu(self):
        base.gameFSM.demand('StartMenu')

    def drawUITask(self, mode, task):
        grade = base.currPlayer.getGrade()
        if grade == 0:
            self.gradeText.setText('A')
            self.gradeText.setFg((0, 1, 0, 1))
        elif grade == 1:
            self.gradeText.setText('B')
            self.gradeText.setFg((0.5, 1, 0, 1))
        elif grade == 2:
            self.gradeText.setText('C')
            self.gradeText.setFg((1, 1, 0, 1))
        elif grade == 3:
            self.gradeText.setText('D')
            self.gradeText.setFg((1, 0.5, 0, 1))
        elif grade == 4:
            self.gradeText.setText('F')
            self.gradeText.setFg((1, 0, 0, 1))
        elif not grade:
            self.gradeText.setText('')

        scoreStr = "score: " + base.currPlayer.getScore()
        self.scoreText.setText(scoreStr)

        comboStr = "combo: " + base.currPlayer.getComboLength()
        self.comboText.setText(comboStr)

        if base.currPlayer.getTiming(): timingStr = "timing: " + base.currPlayer.getTiming()
        else: timingStr = ""
        self.timingText.setText(timingStr)

        if mode == 'battle':
            p1RoundStr = base.player1.getName() + "\n" + str(self.battleData.getRounds(1))
            p2RoundStr = base.player2.getName() + "\n" + str(self.battleData.getRounds(2))
            self.p1RoundText.setText(p1RoundStr)
            self.p2RoundText.setText(p2RoundStr)

            oppScoreStr = "score to beat: " + str(self.battleData.getOppScore())
            self.oppScoreText.setText(oppScoreStr)

        self.uiDrawer.begin()
        timingWidth = 1.5
        stamWidth = 1

        # stambar
        sp = base.currPlayer.stamPercentage()
        self.uiDrawer.rectangleRaw(-timingWidth / 2, 0.15, stamWidth, 0.1, 0, 0, 0, 0,
                                   (0.831081081, 0.33783783783, 1, 1))  # red
        self.uiDrawer.rectangleRaw(-timingWidth / 2, 0.15, stamWidth * sp, 0.1, 0, 0, 0, 0,
                                   (0, 1, 0.4044117647, 1))  # green

        # timingBar
        gp = base.currPlayer.getTimingBarPercentage()

        self.uiDrawer.rectangleRaw(-timingWidth / 2, 0.25, timingWidth, 0.1, 0, 0, 0, 0, (0, 0, 1, 1))
        self.uiDrawer.rectangleRaw(-timingWidth / 2, 0.25, timingWidth * gp, 0.1, 0, 0, 0, 0, (1, 1, 1, 1))

        self.uiDrawer.end()

        return Task.cont

    def FollowCamTask(self, task):
        (ox, oy, oz) = self.trickerDummyNode.getPos()
        (tx, ty, tz) = base.currPlayer.actor.getPos()
        dx = ox - tx
        dy = oy - ty
        error = 0
        nx = 0 # (dx-error) / 100
        ny = 0
        if dy-error == 0: ny = 0
        else:
            try: ny = log(-dy) / 15
            except: self.trickerDummyNode.setPos((base.currPlayer.actor), (0,0,3))
        self.trickerDummyNode.setPos(self.trickerDummyNode, (0,ny,0))
        camera.reparentTo(self.trickerDummyNode)
        camera.setPos(-10, -15, 1)
        camera.lookAt(self.trickerDummyNode)

        return Task.cont

    #this just makes the text object. DO NOT CALL. instead call drawPopupText
    def createPopupText(self,s):
        self.popupText = OnscreenText(text=s, scale = 0.07, parent=render2d,
                                      pos = (0,0.4) )

    def removePopupText(self):
        if self.popupText: self.popupText.detachNode()
        self.popupText = None
        self.popupSeq = None

    def drawPopupText(self, s):
        if not self.popupSeq:
            self.popupSeq = Sequence(Func(self.createPopupText, s),
                     Wait(2),
                     Func(self.removePopupText))
            self.popupSeq.start()

    def destroy(self):
        self.ignoreAll()
        taskMgr.remove('follow')
        taskMgr.remove('drawUI')
        taskMgr.remove('checkTrickState')
        taskMgr.remove('checkGameState')
        taskMgr.remove('reset')
        self.parentNode.removeNode()
        self.startMenuButton.removeNode()
        self.gradeText.removeNode()
        self.scoreText.removeNode()
        self.comboText.removeNode()
        self.timingText.removeNode()
        self.nameText.removeNode()
        self.stamBarText.removeNode()
        self.timeBarText.removeNode()
        self.uiDrawerNode.removeNode()
        base.currPlayer.actor.detach_node()
        self.trickerDummyNode.remove_node()
        self.scene.remove_node()
        base.currPlayer.reset()
        if self.initialDialog: self.initialDialog.detachNode()


import os

from skimage import io
import torch
from torch.autograd import Variable
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torchvision import transforms

import numpy as np
from PIL import Image

from tqdm import auto

from data_loader import RescaleT
from data_loader import ToTensorLab
from data_loader import SalObjDataset

from model import U2NET  # full size version 173.6 MB
from model import U2NETP  # small version u2net 4.7 MB

# normalize the predicted SOD probability map
def normPRED(d):
    ma = torch.max(d)
    mi = torch.min(d)

    dn = (d - mi) / (ma - mi)

    return dn

def save_output(image_name, pred, d_dir):
    predict = pred
    predict = predict.squeeze()
    predict_np = predict.cpu().data.numpy()

    im = Image.fromarray(predict_np * 255).convert("RGB")
    img_name = image_name.split(os.sep)[-1]
    image = io.imread(image_name)
    imo = im.resize((image.shape[1], image.shape[0]), resample=Image.BILINEAR)

    pb_np = np.array(imo)

    aaa = img_name.split(".")
    bbb = aaa[0:-1]
    imidx = bbb[0]
    for i in range(1, len(bbb)):
        imidx = imidx + "." + bbb[i]

    imo.save(d_dir + imidx + ".png")

def main():
    # --------- 1. get image path and name ---------
    model_name = "u2net"  # u2netp

    image_dir = os.path.join(os.getcwd(), "test_data", "test_images")
    prediction_dir = os.path.join(
        os.getcwd(), "test_data", model_name + "_results" + os.sep
    )
    model_dir = os.path.join(
        os.getcwd(), "saved_models", model_name, model_name + ".pth"
    )
    main_path = "/home/piotr/Downloads/carcutter_dataset/background_remove/val/"
    # img_name_list = glob.glob(image_dir + os.sep + "*")
    img_name_list = [main_path + file for file in os.listdir(main_path)]
    print(img_name_list)

    # --------- 2. dataloader ---------
    # 1. dataloader
    test_salobj_dataset = SalObjDataset(
        img_name_list=img_name_list,
        lbl_name_list=[],
        transform=transforms.Compose([RescaleT(320), ToTensorLab()]),
    )
    test_salobj_dataloader = DataLoader(
        test_salobj_dataset, batch_size=1, shuffle=False, num_workers=1
    )

    # --------- 3. model define ---------
    if model_name == "u2net":
        print("...load U2NET---173.6 MB")
        net = U2NET(3, 1)
    elif model_name == "u2netp":
        print("...load U2NEP---4.7 MB")
        net = U2NETP(3, 1)

    if torch.cuda.is_available():
        net.load_state_dict(torch.load("saved_models/trained_models/u2net_2650_0.06782126222969964.pth")["model"])
        net.cuda()
    else:
        net.load_state_dict(
            torch.load("saved_models/trained_models/u2net_interior2.pth", map_location="cpu")[
                "model"])
    net.eval()
    os.makedirs("saved_images", exist_ok=True)
    # --------- 4. inference for each image ---------
    for i_test, data_test in auto.tqdm(enumerate(test_salobj_dataloader)):

        print("inferencing:", img_name_list[i_test].split(os.sep)[-1])

        inputs_test = data_test["image"]
        inputs_test = inputs_test.type(torch.FloatTensor)

        if torch.cuda.is_available():
            inputs_test = Variable(inputs_test.cuda())
        else:
            inputs_test = Variable(inputs_test)

        d1, d2, d3, d4, d5, d6, d7 = net(inputs_test)

        # normalization
        pred = d1[:, 0, :, :].detach()
        img = Image.open(img_name_list[i_test])
        pred = F.interpolate(pred.unsqueeze(0), img.size[::-1])[0].permute(1, 2, 0).numpy()
        img = np.asarray(img)
        pred_img = (img * (1 - pred) + pred * np.array([0, 255, 0])).astype("uint8")
        res_img = np.hstack([pred_img, img])
        # img = Image.fromarray((pred[:, :, 0] * 255).astype("uint8"), "L")
        img = Image.fromarray(res_img)
        img.save(f"saved_images2/{img_name_list[i_test].split('/')[-1]}")

        del d1, d2, d3, d4, d5, d6, d7

if __name__ == "__main__":
    main()