diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -39,7 +39,8 @@ from rhodecode.lib.vcs.utils.helpers imp from rhodecode.lib.vcs.exceptions import VCSError from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib import str2bool, safe_str, get_changeset_safe, safe_unicode +from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \ + safe_unicode from rhodecode.lib.compat import json from rhodecode.lib.caching_query import FromCache @@ -145,12 +146,18 @@ class BaseModel(object): obj = cls.query().get(id_) Session.delete(obj) + def __repr__(self): + if hasattr(self, '__unicode__'): + # python repr needs to return str + return safe_str(self.__unicode__()) + return '' % (self.__class__.__name__) class RhodeCodeSetting(Base, BaseModel): __tablename__ = 'rhodecode_settings' __table_args__ = ( UniqueConstraint('app_settings_name'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -181,8 +188,8 @@ class RhodeCodeSetting(Base, BaseModel): """ self._app_settings_value = safe_unicode(val) - def __repr__(self): - return "<%s('%s:%s')>" % ( + def __unicode__(self): + return u"<%s('%s:%s')>" % ( self.__class__.__name__, self.app_settings_name, self.app_settings_value ) @@ -224,7 +231,8 @@ class RhodeCodeUi(Base, BaseModel): __tablename__ = 'rhodecode_ui' __table_args__ = ( UniqueConstraint('ui_key'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) HOOK_UPDATE = 'changegroup.update' @@ -274,7 +282,8 @@ class User(Base, BaseModel): __tablename__ = 'users' __table_args__ = ( UniqueConstraint('username'), UniqueConstraint('email'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -294,10 +303,15 @@ class User(Base, BaseModel): repositories = relationship('Repository') user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all') + repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all') group_member = relationship('UsersGroupMember', cascade='all') - notifications = relationship('UserNotification',) + notifications = relationship('UserNotification', cascade='all') + # notifications assigned to this user + user_created_notifications = relationship('Notification', cascade='all') + # comments created by this user + user_comments = relationship('ChangesetComment', cascade='all') @hybrid_property def email(self): @@ -328,8 +342,8 @@ class User(Base, BaseModel): def is_admin(self): return self.admin - def __repr__(self): - return "<%s('id:%s:%s')>" % (self.__class__.__name__, + def __unicode__(self): + return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.user_id, self.username) @classmethod @@ -376,6 +390,9 @@ class User(Base, BaseModel): def __json__(self): return dict( + user_id=self.user_id, + first_name=self.name, + last_name=self.lastname, email=self.email, full_name=self.full_name, full_name_or_username=self.full_name_or_username, @@ -386,7 +403,10 @@ class User(Base, BaseModel): class UserLog(Base, BaseModel): __tablename__ = 'user_logs' - __table_args__ = {'extend_existing': True} + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True) @@ -405,7 +425,10 @@ class UserLog(Base, BaseModel): class UsersGroup(Base, BaseModel): __tablename__ = 'users_groups' - __table_args__ = {'extend_existing': True} + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) @@ -413,9 +436,10 @@ class UsersGroup(Base, BaseModel): members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined") users_group_to_perm = relationship('UsersGroupToPerm', cascade='all') + users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all') - def __repr__(self): - return '' % (self.users_group_name) + def __unicode__(self): + return u'' % (self.users_group_name) @classmethod def get_by_group_name(cls, group_name, cache=False, @@ -443,7 +467,10 @@ class UsersGroup(Base, BaseModel): class UsersGroupMember(Base, BaseModel): __tablename__ = 'users_groups_members' - __table_args__ = {'extend_existing': True} + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -461,7 +488,8 @@ class Repository(Base, BaseModel): __tablename__ = 'repositories' __table_args__ = ( UniqueConstraint('repo_name'), - {'extend_existing': True}, + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, ) repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -489,9 +517,9 @@ class Repository(Base, BaseModel): logs = relationship('UserLog') - def __repr__(self): - return "<%s('%s:%s')>" % (self.__class__.__name__, - self.repo_id, self.repo_name) + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__,self.repo_id, + self.repo_name) @classmethod def url_sep(cls): @@ -710,7 +738,8 @@ class RepoGroup(Base, BaseModel): __table_args__ = ( UniqueConstraint('group_name', 'group_parent_id'), CheckConstraint('group_id != group_parent_id'), - {'extend_existing': True}, + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, ) __mapper_args__ = {'order_by': 'group_name'} @@ -728,8 +757,8 @@ class RepoGroup(Base, BaseModel): self.group_name = group_name self.parent_group = parent_group - def __repr__(self): - return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id, + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id, self.group_name) @classmethod @@ -837,13 +866,16 @@ class RepoGroup(Base, BaseModel): class Permission(Base, BaseModel): __tablename__ = 'permissions' - __table_args__ = {'extend_existing': True} + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) - def __repr__(self): - return "<%s('%s:%s')>" % ( + def __unicode__(self): + return u"<%s('%s:%s')>" % ( self.__class__.__name__, self.permission_id, self.permission_name ) @@ -874,7 +906,8 @@ class UserRepoToPerm(Base, BaseModel): __tablename__ = 'repo_to_perm' __table_args__ = ( UniqueConstraint('user_id', 'repository_id', 'permission_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) @@ -894,15 +927,16 @@ class UserRepoToPerm(Base, BaseModel): Session.add(n) return n - def __repr__(self): - return ' %s >' % (self.user, self.repository) + def __unicode__(self): + return u' %s >' % (self.user, self.repository) class UserToPerm(Base, BaseModel): __tablename__ = 'user_to_perm' __table_args__ = ( UniqueConstraint('user_id', 'permission_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) @@ -916,7 +950,8 @@ class UsersGroupRepoToPerm(Base, BaseMod __tablename__ = 'users_group_repo_to_perm' __table_args__ = ( UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -936,15 +971,16 @@ class UsersGroupRepoToPerm(Base, BaseMod Session.add(n) return n - def __repr__(self): - return ' %s >' % (self.users_group, self.repository) + def __unicode__(self): + return u' %s >' % (self.users_group, self.repository) class UsersGroupToPerm(Base, BaseModel): __tablename__ = 'users_group_to_perm' __table_args__ = ( UniqueConstraint('users_group_id', 'permission_id',), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) @@ -958,7 +994,8 @@ class UserRepoGroupToPerm(Base, BaseMode __tablename__ = 'user_repo_group_to_perm' __table_args__ = ( UniqueConstraint('user_id', 'group_id', 'permission_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -975,7 +1012,8 @@ class UsersGroupRepoGroupToPerm(Base, Ba __tablename__ = 'users_group_repo_group_to_perm' __table_args__ = ( UniqueConstraint('users_group_id', 'group_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -990,7 +1028,11 @@ class UsersGroupRepoGroupToPerm(Base, Ba class Statistics(Base, BaseModel): __tablename__ = 'statistics' - __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing': True}) + __table_args__ = ( + UniqueConstraint('repository_id'), + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} + ) stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) @@ -1006,7 +1048,8 @@ class UserFollowing(Base, BaseModel): __table_args__ = ( UniqueConstraint('user_id', 'follows_repository_id'), UniqueConstraint('user_id', 'follows_user_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) @@ -1027,7 +1070,11 @@ class UserFollowing(Base, BaseModel): class CacheInvalidation(Base, BaseModel): __tablename__ = 'cache_invalidation' - __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing': True}) + __table_args__ = ( + UniqueConstraint('cache_key'), + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) @@ -1038,14 +1085,17 @@ class CacheInvalidation(Base, BaseModel) self.cache_args = cache_args self.cache_active = False - def __repr__(self): - return "<%s('%s:%s')>" % (self.__class__.__name__, + def __unicode__(self): + return u"<%s('%s:%s')>" % (self.__class__.__name__, self.cache_id, self.cache_key) + @classmethod + def clear_cache(cls): + cls.query().delete() @classmethod def _get_key(cls, key): """ - Wrapper for generating a key + Wrapper for generating a key, together with a prefix :param key: """ @@ -1054,13 +1104,26 @@ class CacheInvalidation(Base, BaseModel) iid = rhodecode.CONFIG.get('instance_id') if iid: prefix = iid - return "%s%s" % (prefix, key) + return "%s%s" % (prefix, key), prefix, key.rstrip('_README') @classmethod def get_by_key(cls, key): return cls.query().filter(cls.cache_key == key).scalar() @classmethod + def _get_or_create_key(cls, key, prefix, org_key): + inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar() + if not inv_obj: + try: + inv_obj = CacheInvalidation(key, org_key) + Session.add(inv_obj) + Session.commit() + except Exception: + log.error(traceback.format_exc()) + Session.rollback() + return inv_obj + + @classmethod def invalidate(cls, key): """ Returns Invalidation object if this given key should be invalidated @@ -1069,10 +1132,12 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - return cls.query()\ - .filter(CacheInvalidation.cache_key == key)\ - .filter(CacheInvalidation.cache_active == False)\ - .scalar() + + key, _prefix, _org_key = cls._get_key(key) + inv = cls._get_or_create_key(key, _prefix, _org_key) + + if inv and inv.cache_active is False: + return inv @classmethod def set_invalidate(cls, key): @@ -1082,17 +1147,16 @@ class CacheInvalidation(Base, BaseModel) :param key: """ - log.debug('marking %s for invalidation' % key) - inv_obj = Session.query(cls)\ - .filter(cls.cache_key == key).scalar() - if inv_obj: - inv_obj.cache_active = False - else: - log.debug('cache key not found in invalidation db -> creating one') - inv_obj = CacheInvalidation(key) + key, _prefix, _org_key = cls._get_key(key) + inv_objs = Session.query(cls).filter(cls.cache_args == _org_key).all() + log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs), + _org_key)) + try: + for inv_obj in inv_objs: + if inv_obj: + inv_obj.cache_active = False - try: - Session.add(inv_obj) + Session.add(inv_obj) Session.commit() except Exception: log.error(traceback.format_exc()) @@ -1113,7 +1177,10 @@ class CacheInvalidation(Base, BaseModel) class ChangesetComment(Base, BaseModel): __tablename__ = 'changeset_comments' - __table_args__ = ({'extend_existing': True},) + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) revision = Column('revision', String(40), nullable=False) @@ -1142,7 +1209,10 @@ class ChangesetComment(Base, BaseModel): class Notification(Base, BaseModel): __tablename__ = 'notifications' - __table_args__ = ({'extend_existing': True},) + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) TYPE_CHANGESET_COMMENT = u'cs_comment' TYPE_MESSAGE = u'message' @@ -1194,7 +1264,8 @@ class UserNotification(Base, BaseModel): __tablename__ = 'user_to_notification' __table_args__ = ( UniqueConstraint('user_id', 'notification_id'), - {'extend_existing': True} + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'} ) user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True) notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True) @@ -1212,7 +1283,10 @@ class UserNotification(Base, BaseModel): class DbMigrateVersion(Base, BaseModel): __tablename__ = 'db_migrate_version' - __table_args__ = {'extend_existing': True} + __table_args__ = ( + {'extend_existing': True, 'mysql_engine':'InnoDB', + 'mysql_charset': 'utf8'}, + ) repository_id = Column('repository_id', String(250), primary_key=True) repository_path = Column('repository_path', Text) version = Column('version', Integer)