from sqlalchemy import *

class NoSuchTableError(SQLAlchemyError): pass

class TableClassType(type):
    def __getattr__(cls, attr):
        if attr == '_mapper':
            # called during mapper init
            raise AttributeError()
        return getattr(cls._mapper, attr)

def class_for_table(table):
    klass = TableClassType('Class_' + table.name.capitalize(), (object,), {})
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    def __repr__(self):
        import locale
        encoding = locale.getdefaultlocale()[1]
        L = []
        for k in self.__class__.c.keys():
            value = getattr(self, k, '')
            if isinstance(value, unicode):
                value = value.encode(encoding)
            else:
                value = str(value)
            L.append("%s=%r" % (k, value))
        return '%s(%s)' % (self.__class__.__name__, ','.join(L))
    klass.__init__ = __init__
    klass.__repr__ = __repr__
    klass._mapper = mapper(klass, table)
    return klass

class DbSoup:
    def __init__(self, engine):
        self._engine = engine
        self._cache = {}
    def delete(self, *args, **kwargs):
        objectstore.delete(*args, **kwargs)
    def commit(self):
        self._engine.commit()
    def rollback(self):
        self._engine.rollback()
    def _reset(self):
        # for debugging
        self._cache = {}
        self._engine.rollback()
        objectstore.clear()
    def __getattr__(self, attr):
        try:
            t = self._cache[attr]
        except KeyError:
            table = Table(attr, self._engine, autoload=True)
            if table.columns:
                t = class_for_table(table)
            else:
                t = None
            self._cache[attr] = t
        if not t:
            raise NoSuchTableError('%s does not exist' % attr)
        return t
        
if __name__ == '__main__':
    engine = create_engine('postgres', {'database': 'comicfinder', 'user': 'cf', 'password': 'cf'})
    soup = DbSoup(engine)
    print repr(soup.users)

