from sqlalchemy import types
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.schema import Column
from sqlalchemy.types import Integer
import logging


log = logging.getLogger(__name__)
engine = create_engine("mysql+oursql://foo:foo@localhost/foo", echo=True)

class _Base(object):
    __table_args__ = {"mysql_engine":"InnoDB",
                       "mysql_charset":"utf8"}
    def __repr__(self):
        L = []
        for k in self.__class__.__table__.c.keys():
            try:
                value = getattr(self, k)
                L.append("%s=[%r/%s]" % (k, value, type(value)))
            except AttributeError:
                pass
        return '%s(%s)' % (self.__class__.__name__, ','.join(L))

Base = declarative_base(cls=_Base)
    
class Base(Base):
    __tablename__ = 'Bases'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(types.String(80), default="")
    discriminator = Column(types.CHAR(1), nullable=False)
    __mapper_args__ = {'polymorphic_on' : discriminator}

class Mixin:
    mixed = Column("mixed", types.String(80), default="")

class Simple(Base):
    __mapper_args__ = {'polymorphic_identity' : "s"}
        
class MixedFirst(Base, Mixin):
    __mapper_args__ = {'polymorphic_identity' : "b"}
    
class MixedSecond(Base, Mixin):
    __mapper_args__ = {'polymorphic_identity' : "a"}
    file_type = Column(types.String(80), default="")
    

def get_db_session(provided_engine=engine):
    Session = scoped_session(sessionmaker())
    Session.configure(bind=provided_engine)
    return Session

def add_rows(db_session):
    simple = Simple(name='pn')
    mixedFirst = MixedFirst(name='bn', mixed='bg')
    mixedSecond = MixedSecond(name='an', mixed='ag', file_type='aft')
    for x in (simple, mixedFirst, mixedSecond):
        db_session.add(x)    

def run_stuff():
    db_session = get_db_session()
    
    recreate_db()
    add_rows(db_session)

    simple = Simple(name='pn')
    mixedFirst = MixedFirst(name='bn', mixed='bg')
    mixedSecond = MixedSecond(name='an', mixed='ag', file_type='aft')
    for x in (simple, mixedFirst, mixedSecond):
        db_session.add(x)    

    xs = db_session.query(Base).with_polymorphic([Simple, MixedFirst, MixedSecond]).all()
    for x in xs:
        print(x)
        if hasattr(x,"mixed") :
            print(x.mixed)

def recreate_db():
    Base.metadata.drop_all(bind=engine)
    Base.metadata.create_all(bind=engine)
    
if __name__ == "__main__" :
    recreate_db()
    run_stuff()

