Commits

Stéphane Raimbault committed 869122f

Rewrite model.py with the declarative plugin of SA.

Comments (0)

Files changed (3)

transifex/model.py

 from datetime import datetime
 import logging
-from turbogears.database import metadata, mapper, get_engine
 
-# import some basic SQLAlchemy classes for declaring the data model
-# (see http://www.sqlalchemy.org/docs/04/ormtutorial.html)
+from turbogears import identity, config, flash
+from turbogears.database import metadata, mapper
+
 from sqlalchemy import Table, Column, ForeignKey
-from sqlalchemy.orm import relation
-# import some datatypes for table columns from SQLAlchemy
-# (see http://www.sqlalchemy.org/docs/04/types.html for more)
 from sqlalchemy import PickleType, String, Boolean, Unicode, UnicodeText, Integer, DateTime
-from turbogears import identity, config, flash
+from sqlalchemy.orm import relation, backref, synonym
+from sqlalchemy.ext.declarative import declarative_base
+
 from transifex.util import get_user_email
 
 log = logging.getLogger(__name__)
 
-# Bind us to the database defined in the config file.
-#get_engine()
+Base = declarative_base(metadata=metadata, mapper=mapper)
 
-action_log_table =  Table('action_log', metadata, 
-    Column(u'id', Integer(), primary_key=True, nullable=False), 
-    Column(u'user_id', Integer, ForeignKey('tg_user.user_id'), index=True), 
-    Column(u'userinfo', Unicode(255)), 
-    Column(u'module_id', Integer, ForeignKey('module.id'), index=True), 
-    Column(u'branch_id', Integer, ForeignKey('branch.id'), index=True), 
-    Column(u'filenames', UnicodeText()), 
-    Column(u'type', Unicode(32), default=u'submit', nullable=False), 
-    Column(u'summary', Unicode(255)), 
-    Column(u'changelog', UnicodeText()), 
-    Column(u'ip', String(length=40)), 
-    Column(u'diff', UnicodeText()), 
-    Column(u'timestamp', DateTime(timezone=False), default=datetime.now), 
-)
+#
+# Identity
+#
 
-branch_table =  Table('branch', metadata, 
-    Column(u'id', Integer(), primary_key=True, nullable=False), 
-    Column(u'name', Unicode(100), unique=True, nullable=False), 
-    Column(u'description', Unicode(255)), 
-    Column(u'stringfrozen', Boolean(), default=False), 
-)
-
-branch_module_table =  Table('branch_module', metadata, 
-    Column('branch_id', Integer, ForeignKey('branch.id', onupdate='CASCADE', ondelete='CASCADE')), 
-    Column('module_id', Integer, ForeignKey('module.id', onupdate='CASCADE', ondelete='CASCADE'))
-)
-
-module_table =  Table('module', metadata, 
-    Column(u'id', Integer(), primary_key=True, nullable=False), 
-    Column(u'name', Unicode(100), unique=True, nullable=False), 
-    Column(u'description', Unicode(255)), 
-    Column(u'summary', Unicode(255)), 
-    Column(u'repository_id', Integer, ForeignKey('repository.id'), index=True), 
-    Column(u'scmmodule', Unicode(255)), 
-    Column(u'directory', Unicode(255)), 
-    Column(u'filefilter', Unicode(255)), 
-    Column(u'webpage', Unicode(255)), 
-    Column(u'webfrontend', Unicode(255)), 
-    Column(u'changelog', Unicode(255)), 
-    Column(u'popage', Unicode(255)), 
-    Column(u'last_updated', DateTime(timezone=False), default=datetime.now), 
-    Column(u'created', DateTime(timezone=False), default=datetime.now), 
-    Column(u'disabled', Boolean(), default=False), 
-)
-
-repository_table =  Table('repository', metadata, 
-    Column(u'id', Integer(), primary_key=True, nullable=False), 
-    Column(u'name', Unicode(100), unique=True, nullable=False), 
-    Column(u'description', Unicode(255)), 
-    Column(u'summary', Unicode(255)), 
-    Column(u'type', Unicode(32), default=u'cvs', nullable=False), 
-    Column(u'root', Unicode(255)), 
-    Column(u'authtype', Unicode(32), default=u'none',nullable=False), 
-    Column(u'password', Unicode(255)), 
-    Column(u'ssh_key', Unicode(255)), 
-    Column(u'webpage', Unicode(255)), 
-    Column(u'webfrontend', Unicode(255)), 
-    Column(u'created', DateTime(timezone=False), default=datetime.now), 
-    Column(u'disabled', Boolean(), default=False), 
-)
-
-# Identity
-
-visits_table = Table('visit', metadata, 
-    Column('visit_key', String(40), primary_key=True), 
-    Column('created', DateTime, nullable=False, default=datetime.now), 
-    Column('expiry', DateTime)
-)
-
-visit_identity_table = Table('visit_identity', metadata, 
-    Column('visit_key', String(40), primary_key=True), 
-    Column('user_id', Integer, ForeignKey('tg_user.user_id'), index=True)
-)
-
-groups_table = Table('tg_group', metadata, 
-    Column('group_id', Integer, primary_key=True), 
-    Column('group_name', Unicode(16), unique=True), 
-    Column('display_name', Unicode(255)), 
-    Column('created', DateTime, default=datetime.now)
-)
-
-users_table = Table('tg_user', metadata, 
-    Column('user_id', Integer, primary_key=True), 
-    Column('user_name', Unicode(16), unique=True), 
-    Column('email_address', Unicode(255), unique=True), 
-    Column('display_name', Unicode(255)), 
-    Column('password', Unicode(40)), 
-    Column('created', DateTime, default=datetime.now)
-)
-
-permissions_table = Table('permission', metadata, 
-    Column('permission_id', Integer, primary_key=True), 
-    Column('permission_name', Unicode(16), unique=True), 
-    Column('description', Unicode(255))
-)
-
+# This is the association table for the many-to-many relationship between
+# groups and members - this is, the memberships.
 user_group_table = Table('user_group', metadata, 
     Column('user_id', Integer, ForeignKey('tg_user.user_id', 
         onupdate='CASCADE', ondelete='CASCADE')), 
         onupdate='CASCADE', ondelete='CASCADE'))
 )
 
+# This is the association table for the many-to-many relationship between
+# groups and permissions.
 group_permission_table = Table('group_permission', metadata, 
     Column('group_id', Integer, ForeignKey('tg_group.group_id', 
         onupdate='CASCADE', ondelete='CASCADE')), 
-    Column('permission_id', Integer, ForeignKey('permission.permission_id', 
+    Column('permission_id', Integer, ForeignKey('tg_permission.permission_id', 
         onupdate='CASCADE', ondelete='CASCADE'))
 )
 
-# Database Session
-
-session_table = Table('session', metadata,
-    Column('id', String(40), primary_key=True),
-    Column('data', PickleType),
-    Column('expiration_time', DateTime)
-)
-
-
 # the identity model
 
-
-class Visit(object):
+class Visit(Base):
     """
     A visit to your site
     """
+    __tablename__ = 'visit'
+
+    visit_key =  Column(String(40), primary_key=True) 
+    created = Column(DateTime, nullable=False, default=datetime.now)
+    expiry = Column(DateTime)
+
     def lookup_visit(cls, visit_key):
         return cls.query.get(visit_key)
     lookup_visit = classmethod(lookup_visit)
 
 
-class VisitIdentity(object):
+class VisitIdentity(Base):
     """
     A Visit that is link to a User object
     """
-    pass
+    __tablename__ = 'visit_identity'
 
+    visit_key = Column(String(40), autoincrement=True, primary_key=True)
+    user_id = Column(Integer, ForeignKey('tg_user.user_id'))
 
-class Group(object):
+    # Many-to-one
+    # I don't understand why the plural is used for users and the
+    # singular for visit_identity. sra
+    users = relation('User', backref='visit_identity')
+
+
+class Group(Base):
     """
     An ultra-simple group definition.
     """
-    pass
+    __tablename__ = 'tg_group'
 
+    group_id = Column(Integer, autoincrement=True, primary_key=True)
+    group_name = Column(Unicode(16), unique=True)
+    display_name = Column(Unicode(255))
+    created = Column(DateTime, default=datetime.now)
 
-class User(object):
+    # Many-to-many
+    users = relation('User', secondary=user_group_table, backref='groups')
+
+    # Other relationships:
+    # - permissions (many-to-many)
+    
+
+class User(Base):
     """
     Reasonably basic User definition.
     Probably would want additional attributes.
     """
+    __tablename__ = 'tg_user'
+
+    user_id = Column(Integer, autoincrement=True, primary_key=True)
+    user_name = Column(Unicode(16), unique=True)
+    email_address = Column(Unicode(255), unique=True)
+    display_name = Column(Unicode(255))
+    _password = Column('password', Unicode(40))
+
+    created = Column(DateTime, default=datetime.now)
+
+    # Other relationships:
+    #  - groups (many-to-many)
+    #  - visit_identity
+
     def permissions(self):
         perms = set()
         for g in self.groups:
         """
         return self._password
 
-    password = property(_get_password, _set_password)
+    password = synonym('password', descriptor=property(_get_password,
+                                                       _set_password))
 
 
-class Permission(object):
+class Permission(Base):
     """
     A relationship that determines what each Group can do
     """
-    pass
+    __tablename__ = 'tg_permission'
 
-# Session Model
+    permission_id = Column(Integer, autoincrement=True, primary_key=True)
+    permission_name = Column(Unicode(16), unique=True)
+    description = Column(Unicode(255))
 
-class Session(object):
+    # Many-to-many
+    groups = relation(Group, secondary=group_permission_table,
+                      backref='permissions')
+
+class Session(Base):
     """
-    Session
+    Database Session
     """
+    __tablename__ = 'session'
 
+    id = Column(Integer, autoincrement=True, primary_key=True)
+    data = Column(PickleType)
+    expiration_time = Column(DateTime)
 
-class Module(object):
+#
+# Transifex model
+#
+
+branch_module_table =  Table('branch_module', metadata, 
+    Column('branch_id', Integer,
+           ForeignKey('branch.id', onupdate='CASCADE', ondelete='CASCADE')), 
+    Column('module_id', Integer,
+           ForeignKey('module.id', onupdate='CASCADE', ondelete='CASCADE'))
+)
+
+class Module(Base):
     """
     A module in an VCS which could be checked-out, committed, etc.
     """
 
+    __tablename__ = 'module'
+
+    id = Column(Integer, autoincrement=True, primary_key=True)
+    name = Column(Unicode(100), unique=True, nullable=False)
+    description = Column(Unicode(255))
+    summary = Column(Unicode(255))
+    repository_id =  Column(Integer, ForeignKey('repository.id'), index=True)
+    scmmodule = Column(Unicode(255))
+    directory = Column(Unicode(255))
+    filefilter = Column( Unicode(255))
+    webpage = Column(Unicode(255))
+    webfrontend = Column(Unicode(255))
+    changelog = Column(Unicode(255))
+    popage = Column(Unicode(255))
+    last_updated = Column(DateTime(timezone=False), default=datetime.now)
+    created = Column(DateTime(timezone=False), default=datetime.now)
+    disabled = Column(Boolean, default=False)
+
+    # Many-to-many
+    branches = relation('Branch', secondary=branch_module_table, backref='modules')
+
+    # FIXME Not PEP-8 (attribute name)
+    # One-to-many
+    logEntries = relation('ActionLog', backref='module')
+
+    # Other relationships:
+    #  - repository (Many-to-one)
+
     def __str__(self):
         return self.name
 
         filesShown.sort()
         return filesShown
 
-class Repository(object):
+
+class Repository(Base):
     """
     A VCS repository.
     """
-    
-    @classmethod
-    def byName(cls, name):
-        return cls.query.filter_by(name=name).one()
+    __tablename__ = 'repository'
 
-    def __str__(self):
-        return self.name
+    id = Column(Integer, autoincrement=True, primary_key=True)
+    name = Column(Unicode(100), unique=True, nullable=False)
+    description = Column(Unicode(255))
+    summary = Column(Unicode(255))
+    type = Column(Unicode(32), default=u'cvs', nullable=False)
+    root = Column(Unicode(255))
+    authtype = Column(Unicode(32), default=u'none', nullable=False)
+    password = Column(Unicode(255))
+    ssh_key = Column(Unicode(255))
+    webpage = Column(Unicode(255))
+    webfrontend = Column(Unicode(255))
+    created = Column(DateTime(timezone=False), default=datetime.now)
+    disabled = Column(Boolean, default=False)
 
-
-class Branch(object):
-    """
-    A VCS branch.
-    """
+    # One-to-Many
+    modules = relation('Module', backref='repository')
 
     @classmethod
     def byName(cls, name):
         return self.name
 
 
-class ActionLog(object):
+class Branch(Base):
+    """
+    A VCS branch.
+    """
+    __tablename__ = 'branch'
+    
+    id = Column(Integer, autoincrement=True, primary_key=True)
+    name = Column(Unicode(100), unique=True)
+    description = Column(Unicode(255))
+    stringfrozen = Column(Boolean, default=False)
+
+    # FIXME Not PEP-8
+    # One-to-many
+    logEntries = relation('ActionLog', backref='branch')
+
+    # Other relationships:
+    #  - modules (many-to-many)
+ 
+    @classmethod
+    def byName(cls, name):
+        return cls.query.filter_by(name=name).one()
+
+    def __str__(self):
+        return self.name
+
+
+class ActionLog(Base):
     """
     Log for submits of a module
     """
+    __tablename__ = 'action_log'
+    
+    id = Column(Integer, autoincrement=True, primary_key=True)
+    user_id = Column(Integer, ForeignKey('tg_user.user_id'))
+    userinfo = Column(Unicode(255))
+    module_id = Column(Integer, ForeignKey('module.id'))
+    branch_id = Column(Integer, ForeignKey('branch.id'))
+    filenames = Column(UnicodeText())
+    type = Column(Unicode(32), default=u'submit')
+    summary = Column(Unicode(255))
+    changelog = Column(UnicodeText())
+    ip = Column(String(40))
+    diff = Column(UnicodeText)
+    timestamp = Column(DateTime(timezone=False), default=datetime.now)
+    
+    # Other relationships:
+    #  - branch (many-to-one)
+    #  - module (many-to-one)
 
     def __str__(self):
         return self.summary
-
-
-
-# set up mappers between identity tables and classes
-
-mapper(Visit, visits_table)
-
-mapper(VisitIdentity, visit_identity_table, 
-        properties=dict(users=relation(User, backref='visit_identity')))
-
-mapper(User, users_table, 
-        properties=dict(_password=users_table.c.password))
-
-mapper(Group, groups_table,
-       #RelatedJoin 
-        properties=dict(users=relation(User, 
-                secondary=user_group_table, backref='groups')))
-
-mapper(Permission, permissions_table, 
-        properties=dict(groups=relation(Group, 
-                secondary=group_permission_table, backref='permissions')))
-
-#session mapper
-
-mapper(Session, session_table)
-
-# set up mappers between tx tables and classes
-
-mapper(Module, module_table,
-       properties=dict(
-            branches=relation(Branch, secondary=branch_module_table, backref='modules'),
-            logEntries=relation(ActionLog, backref='module')
-))
-
-mapper(Repository, repository_table,
-       properties=dict(
-            modules=relation(Module, backref='repository')
-))
-
-mapper(Branch, branch_table,
-       properties=dict(
-            logEntries=relation(ActionLog, backref='branch')
-))
-
-mapper(ActionLog, action_log_table)

transifex/session_storage.py

 import datetime
 from turbogears.database import session
-from transifex.model import Session, session_table
+from transifex.model import Session
 
 class SQLAlchemyStorage:
     def __init__(self):
         pass
 
     def clean_up(self, sess):
+        session_table = Session.__table__
         result = session_table.delete(
             session_table.c.expiration_time.__lt__(datetime.datetime.now())
             ).execute()
 from optparse import OptionParser
 
 from turbogears import config
+from turbogears.database import session
 
 from transifex.util import header, load_config
 from transifex.model import *
 
-from turbogears.database import metadata, session
-from turbogears.database import bind_meta_data
-
 log = logging.getLogger(__name__)
 
-tx_tables = [users_table, repository_table, module_table, branch_table, action_log_table, branch_module_table]
-
 def get_testing_dir():
     return path.join(config.get("workdir"), "testing-repos")
 
-
 def init_dirs():
     """
     Create some necessary dirs for the app
 
     log.info("Cleaning out tables...")
     
-    #metadata.drop_all(tables=tx_tables)
     metadata.drop_all()
     log.info("Done.\n")
 
     from transifex.model import Branch, Repository, Module, ActionLog, User
 
     log.info("Creating tables...")
-    #metadata.create_all(tables=tx_tables)
     metadata.create_all()
     log.info("Done.\n")
 
 
     load_config(options.config)
 
-    bind_meta_data()
-   
     print header("Transifex initialization")
     if not options.force:
         print """