comparison rhodecode/model/db.py @ 1593:92a4f7c496a5 beta

Correct code style
author Nicolas VINOT <aeris@imirhil.fr>
date Sun, 23 Oct 2011 01:16:55 +0200
parents 8628c8706bf8
children 9dae92a65e40
comparison
equal deleted inserted replaced
1592:8628c8706bf8 1593:92a4f7c496a5
49 49
50 from rhodecode.model.meta import Base, Session 50 from rhodecode.model.meta import Base, Session
51 from rhodecode.model.caching_query import FromCache 51 from rhodecode.model.caching_query import FromCache
52 52
53 53
54 log = logging.getLogger( __name__ ) 54 log = logging.getLogger(__name__)
55 55
56 #============================================================================== 56 #==============================================================================
57 # BASE CLASSES 57 # BASE CLASSES
58 #============================================================================== 58 #==============================================================================
59 59
60 class ModelSerializer( json.JSONEncoder ): 60 class ModelSerializer(json.JSONEncoder):
61 """ 61 """
62 Simple Serializer for JSON, 62 Simple Serializer for JSON,
63 63
64 usage:: 64 usage::
65 65
78 return dict(name=self.name, 78 return dict(name=self.name,
79 value=self.value) 79 value=self.value)
80 80
81 """ 81 """
82 82
83 def default( self, obj ): 83 def default(self, obj):
84 84
85 if hasattr( obj, '__json__' ): 85 if hasattr(obj, '__json__'):
86 return obj.__json__() 86 return obj.__json__()
87 else: 87 else:
88 return json.JSONEncoder.default( self, obj ) 88 return json.JSONEncoder.default(self, obj)
89 89
90 class BaseModel( object ): 90 class BaseModel(object):
91 """Base Model for all classess 91 """Base Model for all classess
92 92
93 """ 93 """
94 94
95 @classmethod 95 @classmethod
96 def _get_keys( cls ): 96 def _get_keys(cls):
97 """return column names for this model """ 97 """return column names for this model """
98 return class_mapper( cls ).c.keys() 98 return class_mapper(cls).c.keys()
99 99
100 def get_dict( self ): 100 def get_dict(self):
101 """return dict with keys and values corresponding 101 """return dict with keys and values corresponding
102 to this model data """ 102 to this model data """
103 103
104 d = {} 104 d = {}
105 for k in self._get_keys(): 105 for k in self._get_keys():
106 d[k] = getattr( self, k ) 106 d[k] = getattr(self, k)
107 return d 107 return d
108 108
109 def get_appstruct( self ): 109 def get_appstruct(self):
110 """return list with keys and values tupples corresponding 110 """return list with keys and values tupples corresponding
111 to this model data """ 111 to this model data """
112 112
113 l = [] 113 l = []
114 for k in self._get_keys(): 114 for k in self._get_keys():
115 l.append( ( k, getattr( self, k ), ) ) 115 l.append((k, getattr(self, k),))
116 return l 116 return l
117 117
118 def populate_obj( self, populate_dict ): 118 def populate_obj(self, populate_dict):
119 """populate model with data from given populate_dict""" 119 """populate model with data from given populate_dict"""
120 120
121 for k in self._get_keys(): 121 for k in self._get_keys():
122 if k in populate_dict: 122 if k in populate_dict:
123 setattr( self, k, populate_dict[k] ) 123 setattr(self, k, populate_dict[k])
124 124
125 @classmethod 125 @classmethod
126 def query( cls ): 126 def query(cls):
127 return Session.query( cls ) 127 return Session.query(cls)
128 128
129 @classmethod 129 @classmethod
130 def get( cls, id_ ): 130 def get(cls, id_):
131 return cls.query().get( id_ ) 131 return cls.query().get(id_)
132 132
133 @classmethod 133 @classmethod
134 def getAll( cls ): 134 def getAll(cls):
135 return cls.query().all() 135 return cls.query().all()
136 136
137 @classmethod 137 @classmethod
138 def delete( cls, id_ ): 138 def delete(cls, id_):
139 obj = cls.query().get( id_ ) 139 obj = cls.query().get(id_)
140 Session.delete( obj ) 140 Session.delete(obj)
141 Session.commit() 141 Session.commit()
142 142
143 143
144 class RhodeCodeSettings( Base, BaseModel ): 144 class RhodeCodeSettings(Base, BaseModel):
145 __tablename__ = 'rhodecode_settings' 145 __tablename__ = 'rhodecode_settings'
146 __table_args__ = ( UniqueConstraint( 'app_settings_name' ), {'extend_existing':True} ) 146 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
147 app_settings_id = Column( "app_settings_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 147 app_settings_id = Column("app_settings_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
148 app_settings_name = Column( "app_settings_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 148 app_settings_name = Column("app_settings_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
149 _app_settings_value = Column( "app_settings_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 149 _app_settings_value = Column("app_settings_value", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
150 150
151 def __init__( self, k = '', v = '' ): 151 def __init__(self, k = '', v = ''):
152 self.app_settings_name = k 152 self.app_settings_name = k
153 self.app_settings_value = v 153 self.app_settings_value = v
154 154
155 155
156 @validates( '_app_settings_value' ) 156 @validates('_app_settings_value')
157 def validate_settings_value( self, key, val ): 157 def validate_settings_value(self, key, val):
158 assert type( val ) == unicode 158 assert type(val) == unicode
159 return val 159 return val
160 160
161 @hybrid_property 161 @hybrid_property
162 def app_settings_value( self ): 162 def app_settings_value(self):
163 v = self._app_settings_value 163 v = self._app_settings_value
164 if v == 'ldap_active': 164 if v == 'ldap_active':
165 v = str2bool( v ) 165 v = str2bool(v)
166 return v 166 return v
167 167
168 @app_settings_value.setter 168 @app_settings_value.setter
169 def app_settings_value( self, val ): 169 def app_settings_value(self, val):
170 """ 170 """
171 Setter that will always make sure we use unicode in app_settings_value 171 Setter that will always make sure we use unicode in app_settings_value
172 172
173 :param val: 173 :param val:
174 """ 174 """
175 self._app_settings_value = safe_unicode( val ) 175 self._app_settings_value = safe_unicode(val)
176 176
177 def __repr__( self ): 177 def __repr__(self):
178 return "<%s('%s:%s')>" % ( self.__class__.__name__, 178 return "<%s('%s:%s')>" % (self.__class__.__name__,
179 self.app_settings_name, self.app_settings_value ) 179 self.app_settings_name, self.app_settings_value)
180 180
181 181
182 @classmethod 182 @classmethod
183 def get_by_name( cls, ldap_key ): 183 def get_by_name(cls, ldap_key):
184 return cls.query()\ 184 return cls.query()\
185 .filter( cls.app_settings_name == ldap_key ).scalar() 185 .filter(cls.app_settings_name == ldap_key).scalar()
186 186
187 @classmethod 187 @classmethod
188 def get_app_settings( cls, cache = False ): 188 def get_app_settings(cls, cache = False):
189 189
190 ret = cls.query() 190 ret = cls.query()
191 191
192 if cache: 192 if cache:
193 ret = ret.options( FromCache( "sql_cache_short", "get_hg_settings" ) ) 193 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
194 194
195 if not ret: 195 if not ret:
196 raise Exception( 'Could not get application settings !' ) 196 raise Exception('Could not get application settings !')
197 settings = {} 197 settings = {}
198 for each in ret: 198 for each in ret:
199 settings['rhodecode_' + each.app_settings_name] = \ 199 settings['rhodecode_' + each.app_settings_name] = \
200 each.app_settings_value 200 each.app_settings_value
201 201
202 return settings 202 return settings
203 203
204 @classmethod 204 @classmethod
205 def get_ldap_settings( cls, cache = False ): 205 def get_ldap_settings(cls, cache = False):
206 ret = cls.query()\ 206 ret = cls.query()\
207 .filter( cls.app_settings_name.startswith( 'ldap_' ) ).all() 207 .filter(cls.app_settings_name.startswith('ldap_')).all()
208 fd = {} 208 fd = {}
209 for row in ret: 209 for row in ret:
210 fd.update( {row.app_settings_name:row.app_settings_value} ) 210 fd.update({row.app_settings_name:row.app_settings_value})
211 211
212 return fd 212 return fd
213 213
214 214
215 class RhodeCodeUi( Base, BaseModel ): 215 class RhodeCodeUi(Base, BaseModel):
216 __tablename__ = 'rhodecode_ui' 216 __tablename__ = 'rhodecode_ui'
217 __table_args__ = ( UniqueConstraint( 'ui_key' ), {'extend_existing':True} ) 217 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
218 218
219 HOOK_UPDATE = 'changegroup.update' 219 HOOK_UPDATE = 'changegroup.update'
220 HOOK_REPO_SIZE = 'changegroup.repo_size' 220 HOOK_REPO_SIZE = 'changegroup.repo_size'
221 HOOK_PUSH = 'pretxnchangegroup.push_logger' 221 HOOK_PUSH = 'pretxnchangegroup.push_logger'
222 HOOK_PULL = 'preoutgoing.pull_logger' 222 HOOK_PULL = 'preoutgoing.pull_logger'
223 223
224 ui_id = Column( "ui_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 224 ui_id = Column("ui_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
225 ui_section = Column( "ui_section", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 225 ui_section = Column("ui_section", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
226 ui_key = Column( "ui_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 226 ui_key = Column("ui_key", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
227 ui_value = Column( "ui_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 227 ui_value = Column("ui_value", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
228 ui_active = Column( "ui_active", Boolean(), nullable = True, unique = None, default = True ) 228 ui_active = Column("ui_active", Boolean(), nullable = True, unique = None, default = True)
229 229
230 230
231 @classmethod 231 @classmethod
232 def get_by_key( cls, key ): 232 def get_by_key(cls, key):
233 return cls.query().filter( cls.ui_key == key ) 233 return cls.query().filter(cls.ui_key == key)
234 234
235 235
236 @classmethod 236 @classmethod
237 def get_builtin_hooks( cls ): 237 def get_builtin_hooks(cls):
238 q = cls.query() 238 q = cls.query()
239 q = q.filter( cls.ui_key.in_( [cls.HOOK_UPDATE, 239 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
240 cls.HOOK_REPO_SIZE, 240 cls.HOOK_REPO_SIZE,
241 cls.HOOK_PUSH, cls.HOOK_PULL] ) ) 241 cls.HOOK_PUSH, cls.HOOK_PULL]))
242 return q.all() 242 return q.all()
243 243
244 @classmethod 244 @classmethod
245 def get_custom_hooks( cls ): 245 def get_custom_hooks(cls):
246 q = cls.query() 246 q = cls.query()
247 q = q.filter( ~cls.ui_key.in_( [cls.HOOK_UPDATE, 247 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
248 cls.HOOK_REPO_SIZE, 248 cls.HOOK_REPO_SIZE,
249 cls.HOOK_PUSH, cls.HOOK_PULL] ) ) 249 cls.HOOK_PUSH, cls.HOOK_PULL]))
250 q = q.filter( cls.ui_section == 'hooks' ) 250 q = q.filter(cls.ui_section == 'hooks')
251 return q.all() 251 return q.all()
252 252
253 @classmethod 253 @classmethod
254 def create_or_update_hook( cls, key, val ): 254 def create_or_update_hook(cls, key, val):
255 new_ui = cls.get_by_key( key ).scalar() or cls() 255 new_ui = cls.get_by_key(key).scalar() or cls()
256 new_ui.ui_section = 'hooks' 256 new_ui.ui_section = 'hooks'
257 new_ui.ui_active = True 257 new_ui.ui_active = True
258 new_ui.ui_key = key 258 new_ui.ui_key = key
259 new_ui.ui_value = val 259 new_ui.ui_value = val
260 260
261 Session.add( new_ui ) 261 Session.add(new_ui)
262 Session.commit() 262 Session.commit()
263 263
264 264
265 class User( Base, BaseModel ): 265 class User(Base, BaseModel):
266 __tablename__ = 'users' 266 __tablename__ = 'users'
267 __table_args__ = ( UniqueConstraint( 'username' ), UniqueConstraint( 'email' ), {'extend_existing':True} ) 267 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
268 user_id = Column( "user_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 268 user_id = Column("user_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
269 username = Column( "username", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 269 username = Column("username", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
270 password = Column( "password", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 270 password = Column("password", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
271 active = Column( "active", Boolean(), nullable = True, unique = None, default = None ) 271 active = Column("active", Boolean(), nullable = True, unique = None, default = None)
272 admin = Column( "admin", Boolean(), nullable = True, unique = None, default = False ) 272 admin = Column("admin", Boolean(), nullable = True, unique = None, default = False)
273 name = Column( "name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 273 name = Column("name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
274 lastname = Column( "lastname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 274 lastname = Column("lastname", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
275 email = Column( "email", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 275 email = Column("email", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
276 last_login = Column( "last_login", DateTime( timezone = False ), nullable = True, unique = None, default = None ) 276 last_login = Column("last_login", DateTime(timezone = False), nullable = True, unique = None, default = None)
277 ldap_dn = Column( "ldap_dn", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 277 ldap_dn = Column("ldap_dn", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
278 api_key = Column( "api_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 278 api_key = Column("api_key", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
279 279
280 user_log = relationship( 'UserLog', cascade = 'all' ) 280 user_log = relationship('UserLog', cascade = 'all')
281 user_perms = relationship( 'UserToPerm', primaryjoin = "User.user_id==UserToPerm.user_id", cascade = 'all' ) 281 user_perms = relationship('UserToPerm', primaryjoin = "User.user_id==UserToPerm.user_id", cascade = 'all')
282 282
283 repositories = relationship( 'Repository' ) 283 repositories = relationship('Repository')
284 user_followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_user_id==User.user_id', cascade = 'all' ) 284 user_followers = relationship('UserFollowing', primaryjoin = 'UserFollowing.follows_user_id==User.user_id', cascade = 'all')
285 repo_to_perm = relationship( 'RepoToPerm', primaryjoin = 'RepoToPerm.user_id==User.user_id', cascade = 'all' ) 285 repo_to_perm = relationship('RepoToPerm', primaryjoin = 'RepoToPerm.user_id==User.user_id', cascade = 'all')
286 286
287 group_member = relationship( 'UsersGroupMember', cascade = 'all' ) 287 group_member = relationship('UsersGroupMember', cascade = 'all')
288 288
289 @property 289 @property
290 def full_contact( self ): 290 def full_contact(self):
291 return '%s %s <%s>' % ( self.name, self.lastname, self.email ) 291 return '%s %s <%s>' % (self.name, self.lastname, self.email)
292 292
293 @property 293 @property
294 def short_contact( self ): 294 def short_contact(self):
295 return '%s %s' % ( self.name, self.lastname ) 295 return '%s %s' % (self.name, self.lastname)
296 296
297 @property 297 @property
298 def is_admin( self ): 298 def is_admin(self):
299 return self.admin 299 return self.admin
300 300
301 def __repr__( self ): 301 def __repr__(self):
302 try: 302 try:
303 return "<%s('id:%s:%s')>" % ( self.__class__.__name__, 303 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
304 self.user_id, self.username ) 304 self.user_id, self.username)
305 except: 305 except:
306 return self.__class__.__name__ 306 return self.__class__.__name__
307 307
308 @classmethod 308 @classmethod
309 def get_by_username( cls, username, case_insensitive = False ): 309 def get_by_username(cls, username, case_insensitive = False):
310 if case_insensitive: 310 if case_insensitive:
311 return Session.query( cls ).filter( cls.username.ilike( username ) ).scalar() 311 return Session.query(cls).filter(cls.username.ilike(username)).scalar()
312 else: 312 else:
313 return Session.query( cls ).filter( cls.username == username ).scalar() 313 return Session.query(cls).filter(cls.username == username).scalar()
314 314
315 @classmethod 315 @classmethod
316 def get_by_api_key( cls, api_key ): 316 def get_by_api_key(cls, api_key):
317 return cls.query().filter( cls.api_key == api_key ).one() 317 return cls.query().filter(cls.api_key == api_key).one()
318 318
319 def update_lastlogin( self ): 319 def update_lastlogin(self):
320 """Update user lastlogin""" 320 """Update user lastlogin"""
321 321
322 self.last_login = datetime.datetime.now() 322 self.last_login = datetime.datetime.now()
323 Session.add( self ) 323 Session.add(self)
324 Session.commit() 324 Session.commit()
325 log.debug( 'updated user %s lastlogin', self.username ) 325 log.debug('updated user %s lastlogin', self.username)
326 326
327 @classmethod 327 @classmethod
328 def create( cls, form_data ): 328 def create(cls, form_data):
329 from rhodecode.lib.auth import get_crypt_password 329 from rhodecode.lib.auth import get_crypt_password
330 330
331 try: 331 try:
332 new_user = cls() 332 new_user = cls()
333 for k, v in form_data.items(): 333 for k, v in form_data.items():
334 if k == 'password': 334 if k == 'password':
335 v = get_crypt_password( v ) 335 v = get_crypt_password(v)
336 setattr( new_user, k, v ) 336 setattr(new_user, k, v)
337 337
338 new_user.api_key = generate_api_key( form_data['username'] ) 338 new_user.api_key = generate_api_key(form_data['username'])
339 Session.add( new_user ) 339 Session.add(new_user)
340 Session.commit() 340 Session.commit()
341 return new_user 341 return new_user
342 except: 342 except:
343 log.error( traceback.format_exc() ) 343 log.error(traceback.format_exc())
344 Session.rollback() 344 Session.rollback()
345 raise 345 raise
346 346
347 class UserLog( Base, BaseModel ): 347 class UserLog(Base, BaseModel):
348 __tablename__ = 'user_logs' 348 __tablename__ = 'user_logs'
349 __table_args__ = {'extend_existing':True} 349 __table_args__ = {'extend_existing':True}
350 user_log_id = Column( "user_log_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 350 user_log_id = Column("user_log_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
351 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 351 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
352 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None ) 352 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable = False, unique = None, default = None)
353 repository_name = Column( "repository_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 353 repository_name = Column("repository_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
354 user_ip = Column( "user_ip", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 354 user_ip = Column("user_ip", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
355 action = Column( "action", UnicodeText( length = 1200000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 355 action = Column("action", UnicodeText(length = 1200000, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
356 action_date = Column( "action_date", DateTime( timezone = False ), nullable = True, unique = None, default = None ) 356 action_date = Column("action_date", DateTime(timezone = False), nullable = True, unique = None, default = None)
357 357
358 @property 358 @property
359 def action_as_day( self ): 359 def action_as_day(self):
360 return date( *self.action_date.timetuple()[:3] ) 360 return date(*self.action_date.timetuple()[:3])
361 361
362 user = relationship( 'User' ) 362 user = relationship('User')
363 repository = relationship( 'Repository' ) 363 repository = relationship('Repository')
364 364
365 365
366 class UsersGroup( Base, BaseModel ): 366 class UsersGroup(Base, BaseModel):
367 __tablename__ = 'users_groups' 367 __tablename__ = 'users_groups'
368 __table_args__ = {'extend_existing':True} 368 __table_args__ = {'extend_existing':True}
369 369
370 users_group_id = Column( "users_group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 370 users_group_id = Column("users_group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
371 users_group_name = Column( "users_group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None ) 371 users_group_name = Column("users_group_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = False, unique = True, default = None)
372 users_group_active = Column( "users_group_active", Boolean(), nullable = True, unique = None, default = None ) 372 users_group_active = Column("users_group_active", Boolean(), nullable = True, unique = None, default = None)
373 373
374 members = relationship( 'UsersGroupMember', cascade = "all, delete, delete-orphan", lazy = "joined" ) 374 members = relationship('UsersGroupMember', cascade = "all, delete, delete-orphan", lazy = "joined")
375 375
376 def __repr__( self ): 376 def __repr__(self):
377 return '<userGroup(%s)>' % ( self.users_group_name ) 377 return '<userGroup(%s)>' % (self.users_group_name)
378 378
379 @classmethod 379 @classmethod
380 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ): 380 def get_by_group_name(cls, group_name, cache = False, case_insensitive = False):
381 if case_insensitive: 381 if case_insensitive:
382 gr = cls.query()\ 382 gr = cls.query()\
383 .filter( cls.users_group_name.ilike( group_name ) ) 383 .filter(cls.users_group_name.ilike(group_name))
384 else: 384 else:
385 gr = cls.query()\ 385 gr = cls.query()\
386 .filter( cls.users_group_name == group_name ) 386 .filter(cls.users_group_name == group_name)
387 if cache: 387 if cache:
388 gr = gr.options( FromCache( "sql_cache_short", 388 gr = gr.options(FromCache("sql_cache_short",
389 "get_user_%s" % group_name ) ) 389 "get_user_%s" % group_name))
390 return gr.scalar() 390 return gr.scalar()
391 391
392 392
393 @classmethod 393 @classmethod
394 def get( cls, users_group_id, cache = False ): 394 def get(cls, users_group_id, cache = False):
395 users_group = cls.query() 395 users_group = cls.query()
396 if cache: 396 if cache:
397 users_group = users_group.options( FromCache( "sql_cache_short", 397 users_group = users_group.options(FromCache("sql_cache_short",
398 "get_users_group_%s" % users_group_id ) ) 398 "get_users_group_%s" % users_group_id))
399 return users_group.get( users_group_id ) 399 return users_group.get(users_group_id)
400 400
401 @classmethod 401 @classmethod
402 def create( cls, form_data ): 402 def create(cls, form_data):
403 try: 403 try:
404 new_users_group = cls() 404 new_users_group = cls()
405 for k, v in form_data.items(): 405 for k, v in form_data.items():
406 setattr( new_users_group, k, v ) 406 setattr(new_users_group, k, v)
407 407
408 Session.add( new_users_group ) 408 Session.add(new_users_group)
409 Session.commit() 409 Session.commit()
410 return new_users_group 410 return new_users_group
411 except: 411 except:
412 log.error( traceback.format_exc() ) 412 log.error(traceback.format_exc())
413 Session.rollback() 413 Session.rollback()
414 raise 414 raise
415 415
416 @classmethod 416 @classmethod
417 def update( cls, users_group_id, form_data ): 417 def update(cls, users_group_id, form_data):
418 418
419 try: 419 try:
420 users_group = cls.get( users_group_id, cache = False ) 420 users_group = cls.get(users_group_id, cache = False)
421 421
422 for k, v in form_data.items(): 422 for k, v in form_data.items():
423 if k == 'users_group_members': 423 if k == 'users_group_members':
424 users_group.members = [] 424 users_group.members = []
425 Session.flush() 425 Session.flush()
426 members_list = [] 426 members_list = []
427 if v: 427 if v:
428 v = [v] if isinstance(v, basestring) else v 428 v = [v] if isinstance(v, basestring) else v
429 for u_id in set(v): 429 for u_id in set(v):
430 member = UsersGroupMember( users_group_id, u_id ) 430 member = UsersGroupMember(users_group_id, u_id)
431 members_list.append( member ) 431 members_list.append(member)
432 setattr( users_group, 'members', members_list ) 432 setattr(users_group, 'members', members_list)
433 setattr( users_group, k, v ) 433 setattr(users_group, k, v)
434 434
435 Session.add( users_group ) 435 Session.add(users_group)
436 Session.commit() 436 Session.commit()
437 except: 437 except:
438 log.error( traceback.format_exc() ) 438 log.error(traceback.format_exc())
439 Session.rollback() 439 Session.rollback()
440 raise 440 raise
441 441
442 @classmethod 442 @classmethod
443 def delete( cls, users_group_id ): 443 def delete(cls, users_group_id):
444 try: 444 try:
445 445
446 # check if this group is not assigned to repo 446 # check if this group is not assigned to repo
447 assigned_groups = UsersGroupRepoToPerm.query()\ 447 assigned_groups = UsersGroupRepoToPerm.query()\
448 .filter( UsersGroupRepoToPerm.users_group_id == 448 .filter(UsersGroupRepoToPerm.users_group_id ==
449 users_group_id ).all() 449 users_group_id).all()
450 450
451 if assigned_groups: 451 if assigned_groups:
452 raise UsersGroupsAssignedException( 'Group assigned to %s' % 452 raise UsersGroupsAssignedException('Group assigned to %s' %
453 assigned_groups ) 453 assigned_groups)
454 454
455 users_group = cls.get( users_group_id, cache = False ) 455 users_group = cls.get(users_group_id, cache = False)
456 Session.delete( users_group ) 456 Session.delete(users_group)
457 Session.commit() 457 Session.commit()
458 except: 458 except:
459 log.error( traceback.format_exc() ) 459 log.error(traceback.format_exc())
460 Session.rollback() 460 Session.rollback()
461 raise 461 raise
462 462
463 class UsersGroupMember( Base, BaseModel ): 463 class UsersGroupMember(Base, BaseModel):
464 __tablename__ = 'users_groups_members' 464 __tablename__ = 'users_groups_members'
465 __table_args__ = {'extend_existing':True} 465 __table_args__ = {'extend_existing':True}
466 466
467 users_group_member_id = Column( "users_group_member_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 467 users_group_member_id = Column("users_group_member_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
468 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None ) 468 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable = False, unique = None, default = None)
469 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 469 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
470 470
471 user = relationship( 'User', lazy = 'joined' ) 471 user = relationship('User', lazy = 'joined')
472 users_group = relationship( 'UsersGroup' ) 472 users_group = relationship('UsersGroup')
473 473
474 def __init__( self, gr_id = '', u_id = '' ): 474 def __init__(self, gr_id = '', u_id = ''):
475 self.users_group_id = gr_id 475 self.users_group_id = gr_id
476 self.user_id = u_id 476 self.user_id = u_id
477 477
478 @staticmethod 478 @staticmethod
479 def add_user_to_group( group, user ): 479 def add_user_to_group(group, user):
480 ugm = UsersGroupMember() 480 ugm = UsersGroupMember()
481 ugm.users_group = group 481 ugm.users_group = group
482 ugm.user = user 482 ugm.user = user
483 Session.add( ugm ) 483 Session.add(ugm)
484 Session.commit() 484 Session.commit()
485 return ugm 485 return ugm
486 486
487 class Repository( Base, BaseModel ): 487 class Repository(Base, BaseModel):
488 __tablename__ = 'repositories' 488 __tablename__ = 'repositories'
489 __table_args__ = ( UniqueConstraint( 'repo_name' ), {'extend_existing':True}, ) 489 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
490 490
491 repo_id = Column( "repo_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 491 repo_id = Column("repo_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
492 repo_name = Column( "repo_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None ) 492 repo_name = Column("repo_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = False, unique = True, default = None)
493 clone_uri = Column( "clone_uri", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = False, default = None ) 493 clone_uri = Column("clone_uri", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = False, default = None)
494 repo_type = Column( "repo_type", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = False, default = 'hg' ) 494 repo_type = Column("repo_type", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = False, unique = False, default = 'hg')
495 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = False, default = None ) 495 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = False, default = None)
496 private = Column( "private", Boolean(), nullable = True, unique = None, default = None ) 496 private = Column("private", Boolean(), nullable = True, unique = None, default = None)
497 enable_statistics = Column( "statistics", Boolean(), nullable = True, unique = None, default = True ) 497 enable_statistics = Column("statistics", Boolean(), nullable = True, unique = None, default = True)
498 enable_downloads = Column( "downloads", Boolean(), nullable = True, unique = None, default = True ) 498 enable_downloads = Column("downloads", Boolean(), nullable = True, unique = None, default = True)
499 description = Column( "description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 499 description = Column("description", String(length = 10000, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
500 created_on = Column( 'created_on', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now ) 500 created_on = Column('created_on', DateTime(timezone = False), nullable = True, unique = None, default = datetime.datetime.now)
501 501
502 fork_id = Column( "fork_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = False, default = None ) 502 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable = True, unique = False, default = None)
503 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = False, default = None ) 503 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable = True, unique = False, default = None)
504 504
505 505
506 user = relationship( 'User' ) 506 user = relationship('User')
507 fork = relationship( 'Repository', remote_side = repo_id ) 507 fork = relationship('Repository', remote_side = repo_id)
508 group = relationship( 'Group' ) 508 group = relationship('Group')
509 repo_to_perm = relationship( 'RepoToPerm', cascade = 'all', order_by = 'RepoToPerm.repo_to_perm_id' ) 509 repo_to_perm = relationship('RepoToPerm', cascade = 'all', order_by = 'RepoToPerm.repo_to_perm_id')
510 users_group_to_perm = relationship( 'UsersGroupRepoToPerm', cascade = 'all' ) 510 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade = 'all')
511 stats = relationship( 'Statistics', cascade = 'all', uselist = False ) 511 stats = relationship('Statistics', cascade = 'all', uselist = False)
512 512
513 followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_repo_id==Repository.repo_id', cascade = 'all' ) 513 followers = relationship('UserFollowing', primaryjoin = 'UserFollowing.follows_repo_id==Repository.repo_id', cascade = 'all')
514 514
515 logs = relationship( 'UserLog', cascade = 'all' ) 515 logs = relationship('UserLog', cascade = 'all')
516 516
517 def __repr__( self ): 517 def __repr__(self):
518 return "<%s('%s:%s')>" % ( self.__class__.__name__, 518 return "<%s('%s:%s')>" % (self.__class__.__name__,
519 self.repo_id, self.repo_name ) 519 self.repo_id, self.repo_name)
520 520
521 @classmethod 521 @classmethod
522 def url_sep( cls ): 522 def url_sep(cls):
523 return '/' 523 return '/'
524 524
525 @classmethod 525 @classmethod
526 def get_by_repo_name( cls, repo_name ): 526 def get_by_repo_name(cls, repo_name):
527 q = Session.query( cls ).filter( cls.repo_name == repo_name ) 527 q = Session.query(cls).filter(cls.repo_name == repo_name)
528 q = q.options( joinedload( Repository.fork ) )\ 528 q = q.options(joinedload(Repository.fork))\
529 .options( joinedload( Repository.user ) )\ 529 .options(joinedload(Repository.user))\
530 .options( joinedload( Repository.group ) ) 530 .options(joinedload(Repository.group))
531 return q.one() 531 return q.one()
532 532
533 @classmethod 533 @classmethod
534 def get_repo_forks( cls, repo_id ): 534 def get_repo_forks(cls, repo_id):
535 return cls.query().filter( Repository.fork_id == repo_id ) 535 return cls.query().filter(Repository.fork_id == repo_id)
536 536
537 @classmethod 537 @classmethod
538 def base_path( cls ): 538 def base_path(cls):
539 """ 539 """
540 Returns base path when all repos are stored 540 Returns base path when all repos are stored
541 541
542 :param cls: 542 :param cls:
543 """ 543 """
544 q = Session.query( RhodeCodeUi ).filter( RhodeCodeUi.ui_key == 544 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
545 cls.url_sep() ) 545 cls.url_sep())
546 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) ) 546 q.options(FromCache("sql_cache_short", "repository_repo_path"))
547 return q.one().ui_value 547 return q.one().ui_value
548 548
549 @property 549 @property
550 def just_name( self ): 550 def just_name(self):
551 return self.repo_name.split( Repository.url_sep() )[-1] 551 return self.repo_name.split(Repository.url_sep())[-1]
552 552
553 @property 553 @property
554 def groups_with_parents( self ): 554 def groups_with_parents(self):
555 groups = [] 555 groups = []
556 if self.group is None: 556 if self.group is None:
557 return groups 557 return groups
558 558
559 cur_gr = self.group 559 cur_gr = self.group
560 groups.insert( 0, cur_gr ) 560 groups.insert(0, cur_gr)
561 while 1: 561 while 1:
562 gr = getattr( cur_gr, 'parent_group', None ) 562 gr = getattr(cur_gr, 'parent_group', None)
563 cur_gr = cur_gr.parent_group 563 cur_gr = cur_gr.parent_group
564 if gr is None: 564 if gr is None:
565 break 565 break
566 groups.insert( 0, gr ) 566 groups.insert(0, gr)
567 567
568 return groups 568 return groups
569 569
570 @property 570 @property
571 def groups_and_repo( self ): 571 def groups_and_repo(self):
572 return self.groups_with_parents, self.just_name 572 return self.groups_with_parents, self.just_name
573 573
574 @LazyProperty 574 @LazyProperty
575 def repo_path( self ): 575 def repo_path(self):
576 """ 576 """
577 Returns base full path for that repository means where it actually 577 Returns base full path for that repository means where it actually
578 exists on a filesystem 578 exists on a filesystem
579 """ 579 """
580 q = Session.query( RhodeCodeUi ).filter( RhodeCodeUi.ui_key == 580 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
581 Repository.url_sep() ) 581 Repository.url_sep())
582 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) ) 582 q.options(FromCache("sql_cache_short", "repository_repo_path"))
583 return q.one().ui_value 583 return q.one().ui_value
584 584
585 @property 585 @property
586 def repo_full_path( self ): 586 def repo_full_path(self):
587 p = [self.repo_path] 587 p = [self.repo_path]
588 # we need to split the name by / since this is how we store the 588 # we need to split the name by / since this is how we store the
589 # names in the database, but that eventually needs to be converted 589 # names in the database, but that eventually needs to be converted
590 # into a valid system path 590 # into a valid system path
591 p += self.repo_name.split( Repository.url_sep() ) 591 p += self.repo_name.split(Repository.url_sep())
592 return os.path.join( *p ) 592 return os.path.join(*p)
593 593
594 def get_new_name( self, repo_name ): 594 def get_new_name(self, repo_name):
595 """ 595 """
596 returns new full repository name based on assigned group and new new 596 returns new full repository name based on assigned group and new new
597 597
598 :param group_name: 598 :param group_name:
599 """ 599 """
600 path_prefix = self.group.full_path_splitted if self.group else [] 600 path_prefix = self.group.full_path_splitted if self.group else []
601 return Repository.url_sep().join( path_prefix + [repo_name] ) 601 return Repository.url_sep().join(path_prefix + [repo_name])
602 602
603 @property 603 @property
604 def _ui( self ): 604 def _ui(self):
605 """ 605 """
606 Creates an db based ui object for this repository 606 Creates an db based ui object for this repository
607 """ 607 """
608 from mercurial import ui 608 from mercurial import ui
609 from mercurial import config 609 from mercurial import config
614 baseui._ucfg = config.config() 614 baseui._ucfg = config.config()
615 baseui._tcfg = config.config() 615 baseui._tcfg = config.config()
616 616
617 617
618 ret = RhodeCodeUi.query()\ 618 ret = RhodeCodeUi.query()\
619 .options( FromCache( "sql_cache_short", "repository_repo_ui" ) ).all() 619 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
620 620
621 hg_ui = ret 621 hg_ui = ret
622 for ui_ in hg_ui: 622 for ui_ in hg_ui:
623 if ui_.ui_active: 623 if ui_.ui_active:
624 log.debug( 'settings ui from db[%s]%s:%s', ui_.ui_section, 624 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
625 ui_.ui_key, ui_.ui_value ) 625 ui_.ui_key, ui_.ui_value)
626 baseui.setconfig( ui_.ui_section, ui_.ui_key, ui_.ui_value ) 626 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
627 627
628 return baseui 628 return baseui
629 629
630 @classmethod 630 @classmethod
631 def is_valid( cls, repo_name ): 631 def is_valid(cls, repo_name):
632 """ 632 """
633 returns True if given repo name is a valid filesystem repository 633 returns True if given repo name is a valid filesystem repository
634 634
635 @param cls: 635 @param cls:
636 @param repo_name: 636 @param repo_name:
637 """ 637 """
638 from rhodecode.lib.utils import is_valid_repo 638 from rhodecode.lib.utils import is_valid_repo
639 639
640 return is_valid_repo( repo_name, cls.base_path() ) 640 return is_valid_repo(repo_name, cls.base_path())
641 641
642 642
643 #========================================================================== 643 #==========================================================================
644 # SCM PROPERTIES 644 # SCM PROPERTIES
645 #========================================================================== 645 #==========================================================================
646 646
647 def get_changeset( self, rev ): 647 def get_changeset(self, rev):
648 return get_changeset_safe( self.scm_instance, rev ) 648 return get_changeset_safe(self.scm_instance, rev)
649 649
650 @property 650 @property
651 def tip( self ): 651 def tip(self):
652 return self.get_changeset( 'tip' ) 652 return self.get_changeset('tip')
653 653
654 @property 654 @property
655 def author( self ): 655 def author(self):
656 return self.tip.author 656 return self.tip.author
657 657
658 @property 658 @property
659 def last_change( self ): 659 def last_change(self):
660 return self.scm_instance.last_change 660 return self.scm_instance.last_change
661 661
662 #========================================================================== 662 #==========================================================================
663 # SCM CACHE INSTANCE 663 # SCM CACHE INSTANCE
664 #========================================================================== 664 #==========================================================================
665 665
666 @property 666 @property
667 def invalidate( self ): 667 def invalidate(self):
668 """ 668 """
669 Returns Invalidation object if this repo should be invalidated 669 Returns Invalidation object if this repo should be invalidated
670 None otherwise. `cache_active = False` means that this cache 670 None otherwise. `cache_active = False` means that this cache
671 state is not valid and needs to be invalidated 671 state is not valid and needs to be invalidated
672 """ 672 """
673 return CacheInvalidation.query()\ 673 return CacheInvalidation.query()\
674 .filter( CacheInvalidation.cache_key == self.repo_name )\ 674 .filter(CacheInvalidation.cache_key == self.repo_name)\
675 .filter( CacheInvalidation.cache_active == False )\ 675 .filter(CacheInvalidation.cache_active == False)\
676 .scalar() 676 .scalar()
677 677
678 def set_invalidate( self ): 678 def set_invalidate(self):
679 """ 679 """
680 set a cache for invalidation for this instance 680 set a cache for invalidation for this instance
681 """ 681 """
682 inv = CacheInvalidation.query()\ 682 inv = CacheInvalidation.query()\
683 .filter( CacheInvalidation.cache_key == self.repo_name )\ 683 .filter(CacheInvalidation.cache_key == self.repo_name)\
684 .scalar() 684 .scalar()
685 685
686 if inv is None: 686 if inv is None:
687 inv = CacheInvalidation( self.repo_name ) 687 inv = CacheInvalidation(self.repo_name)
688 inv.cache_active = True 688 inv.cache_active = True
689 Session.add( inv ) 689 Session.add(inv)
690 Session.commit() 690 Session.commit()
691 691
692 @LazyProperty 692 @LazyProperty
693 def scm_instance( self ): 693 def scm_instance(self):
694 return self.__get_instance() 694 return self.__get_instance()
695 695
696 @property 696 @property
697 def scm_instance_cached( self ): 697 def scm_instance_cached(self):
698 @cache_region( 'long_term' ) 698 @cache_region('long_term')
699 def _c( repo_name ): 699 def _c(repo_name):
700 return self.__get_instance() 700 return self.__get_instance()
701 701
702 # TODO: remove this trick when beaker 1.6 is released 702 # TODO: remove this trick when beaker 1.6 is released
703 # and have fixed this issue with not supporting unicode keys 703 # and have fixed this issue with not supporting unicode keys
704 rn = safe_str( self.repo_name ) 704 rn = safe_str(self.repo_name)
705 705
706 inv = self.invalidate 706 inv = self.invalidate
707 if inv is not None: 707 if inv is not None:
708 region_invalidate( _c, None, rn ) 708 region_invalidate(_c, None, rn)
709 # update our cache 709 # update our cache
710 inv.cache_active = True 710 inv.cache_active = True
711 Session.add( inv ) 711 Session.add(inv)
712 Session.commit() 712 Session.commit()
713 713
714 return _c( rn ) 714 return _c(rn)
715 715
716 def __get_instance( self ): 716 def __get_instance(self):
717 717
718 repo_full_path = self.repo_full_path 718 repo_full_path = self.repo_full_path
719 719
720 try: 720 try:
721 alias = get_scm( repo_full_path )[0] 721 alias = get_scm(repo_full_path)[0]
722 log.debug( 'Creating instance of %s repository', alias ) 722 log.debug('Creating instance of %s repository', alias)
723 backend = get_backend( alias ) 723 backend = get_backend(alias)
724 except VCSError: 724 except VCSError:
725 log.error( traceback.format_exc() ) 725 log.error(traceback.format_exc())
726 log.error( 'Perhaps this repository is in db and not in ' 726 log.error('Perhaps this repository is in db and not in '
727 'filesystem run rescan repositories with ' 727 'filesystem run rescan repositories with '
728 '"destroy old data " option from admin panel' ) 728 '"destroy old data " option from admin panel')
729 return 729 return
730 730
731 if alias == 'hg': 731 if alias == 'hg':
732 732
733 repo = backend( safe_str( repo_full_path ), create = False, 733 repo = backend(safe_str(repo_full_path), create = False,
734 baseui = self._ui ) 734 baseui = self._ui)
735 #skip hidden web repository 735 #skip hidden web repository
736 if repo._get_hidden(): 736 if repo._get_hidden():
737 return 737 return
738 else: 738 else:
739 repo = backend( repo_full_path, create = False ) 739 repo = backend(repo_full_path, create = False)
740 740
741 return repo 741 return repo
742 742
743 743
744 class Group( Base, BaseModel ): 744 class Group(Base, BaseModel):
745 __tablename__ = 'groups' 745 __tablename__ = 'groups'
746 __table_args__ = ( UniqueConstraint( 'group_name', 'group_parent_id' ), 746 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
747 CheckConstraint( 'group_id != group_parent_id' ), {'extend_existing':True}, ) 747 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
748 __mapper_args__ = {'order_by':'group_name'} 748 __mapper_args__ = {'order_by':'group_name'}
749 749
750 group_id = Column( "group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 750 group_id = Column("group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
751 group_name = Column( "group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None ) 751 group_name = Column("group_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = False, unique = True, default = None)
752 group_parent_id = Column( "group_parent_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = None, default = None ) 752 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable = True, unique = None, default = None)
753 group_description = Column( "group_description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 753 group_description = Column("group_description", String(length = 10000, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
754 754
755 parent_group = relationship( 'Group', remote_side = group_id ) 755 parent_group = relationship('Group', remote_side = group_id)
756 756
757 757
758 def __init__( self, group_name = '', parent_group = None ): 758 def __init__(self, group_name = '', parent_group = None):
759 self.group_name = group_name 759 self.group_name = group_name
760 self.parent_group = parent_group 760 self.parent_group = parent_group
761 761
762 def __repr__( self ): 762 def __repr__(self):
763 return "<%s('%s:%s')>" % ( self.__class__.__name__, self.group_id, 763 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
764 self.group_name ) 764 self.group_name)
765 765
766 @classmethod 766 @classmethod
767 def groups_choices( cls ): 767 def groups_choices(cls):
768 from webhelpers.html import literal as _literal 768 from webhelpers.html import literal as _literal
769 repo_groups = [( '', '' )] 769 repo_groups = [('', '')]
770 sep = ' &raquo; ' 770 sep = ' &raquo; '
771 _name = lambda k: _literal( sep.join( k ) ) 771 _name = lambda k: _literal(sep.join(k))
772 772
773 repo_groups.extend( [( x.group_id, _name( x.full_path_splitted ) ) 773 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
774 for x in cls.query().all()] ) 774 for x in cls.query().all()])
775 775
776 repo_groups = sorted( repo_groups, key = lambda t: t[1].split( sep )[0] ) 776 repo_groups = sorted(repo_groups, key = lambda t: t[1].split(sep)[0])
777 return repo_groups 777 return repo_groups
778 778
779 @classmethod 779 @classmethod
780 def url_sep( cls ): 780 def url_sep(cls):
781 return '/' 781 return '/'
782 782
783 @classmethod 783 @classmethod
784 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ): 784 def get_by_group_name(cls, group_name, cache = False, case_insensitive = False):
785 if case_insensitive: 785 if case_insensitive:
786 gr = cls.query()\ 786 gr = cls.query()\
787 .filter( cls.group_name.ilike( group_name ) ) 787 .filter(cls.group_name.ilike(group_name))
788 else: 788 else:
789 gr = cls.query()\ 789 gr = cls.query()\
790 .filter( cls.group_name == group_name ) 790 .filter(cls.group_name == group_name)
791 if cache: 791 if cache:
792 gr = gr.options( FromCache( "sql_cache_short", 792 gr = gr.options(FromCache("sql_cache_short",
793 "get_group_%s" % group_name ) ) 793 "get_group_%s" % group_name))
794 return gr.scalar() 794 return gr.scalar()
795 795
796 @property 796 @property
797 def parents( self ): 797 def parents(self):
798 parents_recursion_limit = 5 798 parents_recursion_limit = 5
799 groups = [] 799 groups = []
800 if self.parent_group is None: 800 if self.parent_group is None:
801 return groups 801 return groups
802 cur_gr = self.parent_group 802 cur_gr = self.parent_group
803 groups.insert( 0, cur_gr ) 803 groups.insert(0, cur_gr)
804 cnt = 0 804 cnt = 0
805 while 1: 805 while 1:
806 cnt += 1 806 cnt += 1
807 gr = getattr( cur_gr, 'parent_group', None ) 807 gr = getattr(cur_gr, 'parent_group', None)
808 cur_gr = cur_gr.parent_group 808 cur_gr = cur_gr.parent_group
809 if gr is None: 809 if gr is None:
810 break 810 break
811 if cnt == parents_recursion_limit: 811 if cnt == parents_recursion_limit:
812 # this will prevent accidental infinit loops 812 # this will prevent accidental infinit loops
813 log.error( 'group nested more than %s' % 813 log.error('group nested more than %s' %
814 parents_recursion_limit ) 814 parents_recursion_limit)
815 break 815 break
816 816
817 groups.insert( 0, gr ) 817 groups.insert(0, gr)
818 return groups 818 return groups
819 819
820 @property 820 @property
821 def children( self ): 821 def children(self):
822 return Group.query().filter( Group.parent_group == self ) 822 return Group.query().filter(Group.parent_group == self)
823 823
824 @property 824 @property
825 def name( self ): 825 def name(self):
826 return self.group_name.split( Group.url_sep() )[-1] 826 return self.group_name.split(Group.url_sep())[-1]
827 827
828 @property 828 @property
829 def full_path( self ): 829 def full_path(self):
830 return Group.url_sep().join( [g.group_name for g in self.parents] + 830 return Group.url_sep().join([g.group_name for g in self.parents] +
831 [self.group_name] ) 831 [self.group_name])
832 832
833 @property 833 @property
834 def full_path_splitted( self ): 834 def full_path_splitted(self):
835 return self.group_name.split( Group.url_sep() ) 835 return self.group_name.split(Group.url_sep())
836 836
837 @property 837 @property
838 def repositories( self ): 838 def repositories(self):
839 return Repository.query().filter( Repository.group == self ) 839 return Repository.query().filter(Repository.group == self)
840 840
841 @property 841 @property
842 def repositories_recursive_count( self ): 842 def repositories_recursive_count(self):
843 cnt = self.repositories.count() 843 cnt = self.repositories.count()
844 844
845 def children_count( group ): 845 def children_count(group):
846 cnt = 0 846 cnt = 0
847 for child in group.children: 847 for child in group.children:
848 cnt += child.repositories.count() 848 cnt += child.repositories.count()
849 cnt += children_count( child ) 849 cnt += children_count(child)
850 return cnt 850 return cnt
851 851
852 return cnt + children_count( self ) 852 return cnt + children_count(self)
853 853
854 854
855 def get_new_name( self, group_name ): 855 def get_new_name(self, group_name):
856 """ 856 """
857 returns new full group name based on parent and new name 857 returns new full group name based on parent and new name
858 858
859 :param group_name: 859 :param group_name:
860 """ 860 """
861 path_prefix = self.parent_group.full_path_splitted if self.parent_group else [] 861 path_prefix = self.parent_group.full_path_splitted if self.parent_group else []
862 return Group.url_sep().join( path_prefix + [group_name] ) 862 return Group.url_sep().join(path_prefix + [group_name])
863 863
864 864
865 class Permission( Base, BaseModel ): 865 class Permission(Base, BaseModel):
866 __tablename__ = 'permissions' 866 __tablename__ = 'permissions'
867 __table_args__ = {'extend_existing':True} 867 __table_args__ = {'extend_existing':True}
868 permission_id = Column( "permission_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 868 permission_id = Column("permission_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
869 permission_name = Column( "permission_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 869 permission_name = Column("permission_name", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
870 permission_longname = Column( "permission_longname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 870 permission_longname = Column("permission_longname", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
871 871
872 def __repr__( self ): 872 def __repr__(self):
873 return "<%s('%s:%s')>" % ( self.__class__.__name__, 873 return "<%s('%s:%s')>" % (self.__class__.__name__,
874 self.permission_id, self.permission_name ) 874 self.permission_id, self.permission_name)
875 875
876 @classmethod 876 @classmethod
877 def get_by_key( cls, key ): 877 def get_by_key(cls, key):
878 return cls.query().filter( cls.permission_name == key ).scalar() 878 return cls.query().filter(cls.permission_name == key).scalar()
879 879
880 class RepoToPerm( Base, BaseModel ): 880 class RepoToPerm(Base, BaseModel):
881 __tablename__ = 'repo_to_perm' 881 __tablename__ = 'repo_to_perm'
882 __table_args__ = ( UniqueConstraint( 'user_id', 'repository_id' ), {'extend_existing':True} ) 882 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
883 repo_to_perm_id = Column( "repo_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 883 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
884 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 884 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
885 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None ) 885 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable = False, unique = None, default = None)
886 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None ) 886 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable = False, unique = None, default = None)
887 887
888 user = relationship( 'User' ) 888 user = relationship('User')
889 permission = relationship( 'Permission' ) 889 permission = relationship('Permission')
890 repository = relationship( 'Repository' ) 890 repository = relationship('Repository')
891 891
892 class UserToPerm( Base, BaseModel ): 892 class UserToPerm(Base, BaseModel):
893 __tablename__ = 'user_to_perm' 893 __tablename__ = 'user_to_perm'
894 __table_args__ = ( UniqueConstraint( 'user_id', 'permission_id' ), {'extend_existing':True} ) 894 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
895 user_to_perm_id = Column( "user_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 895 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
896 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 896 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
897 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None ) 897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable = False, unique = None, default = None)
898 898
899 user = relationship( 'User' ) 899 user = relationship('User')
900 permission = relationship( 'Permission' ) 900 permission = relationship('Permission')
901 901
902 @classmethod 902 @classmethod
903 def has_perm( cls, user_id, perm ): 903 def has_perm(cls, user_id, perm):
904 if not isinstance( perm, Permission ): 904 if not isinstance(perm, Permission):
905 raise Exception( 'perm needs to be an instance of Permission class' ) 905 raise Exception('perm needs to be an instance of Permission class')
906 906
907 return cls.query().filter( cls.user_id == user_id )\ 907 return cls.query().filter(cls.user_id == user_id)\
908 .filter( cls.permission == perm ).scalar() is not None 908 .filter(cls.permission == perm).scalar() is not None
909 909
910 @classmethod 910 @classmethod
911 def grant_perm( cls, user_id, perm ): 911 def grant_perm(cls, user_id, perm):
912 if not isinstance( perm, Permission ): 912 if not isinstance(perm, Permission):
913 raise Exception( 'perm needs to be an instance of Permission class' ) 913 raise Exception('perm needs to be an instance of Permission class')
914 914
915 new = cls() 915 new = cls()
916 new.user_id = user_id 916 new.user_id = user_id
917 new.permission = perm 917 new.permission = perm
918 try: 918 try:
919 Session.add( new ) 919 Session.add(new)
920 Session.commit() 920 Session.commit()
921 except: 921 except:
922 Session.rollback() 922 Session.rollback()
923 923
924 924
925 @classmethod 925 @classmethod
926 def revoke_perm( cls, user_id, perm ): 926 def revoke_perm(cls, user_id, perm):
927 if not isinstance( perm, Permission ): 927 if not isinstance(perm, Permission):
928 raise Exception( 'perm needs to be an instance of Permission class' ) 928 raise Exception('perm needs to be an instance of Permission class')
929 929
930 try: 930 try:
931 cls.query().filter( cls.user_id == user_id )\ 931 cls.query().filter(cls.user_id == user_id)\
932 .filter( cls.permission == perm ).delete() 932 .filter(cls.permission == perm).delete()
933 Session.commit() 933 Session.commit()
934 except: 934 except:
935 Session.rollback() 935 Session.rollback()
936 936
937 class UsersGroupRepoToPerm( Base, BaseModel ): 937 class UsersGroupRepoToPerm(Base, BaseModel):
938 __tablename__ = 'users_group_repo_to_perm' 938 __tablename__ = 'users_group_repo_to_perm'
939 __table_args__ = ( UniqueConstraint( 'repository_id', 'users_group_id', 'permission_id' ), {'extend_existing':True} ) 939 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
940 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 940 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
941 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None ) 941 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable = False, unique = None, default = None)
942 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None ) 942 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable = False, unique = None, default = None)
943 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None ) 943 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable = False, unique = None, default = None)
944 944
945 users_group = relationship( 'UsersGroup' ) 945 users_group = relationship('UsersGroup')
946 permission = relationship( 'Permission' ) 946 permission = relationship('Permission')
947 repository = relationship( 'Repository' ) 947 repository = relationship('Repository')
948 948
949 def __repr__( self ): 949 def __repr__(self):
950 return '<userGroup:%s => %s >' % ( self.users_group, self.repository ) 950 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
951 951
952 class UsersGroupToPerm( Base, BaseModel ): 952 class UsersGroupToPerm(Base, BaseModel):
953 __tablename__ = 'users_group_to_perm' 953 __tablename__ = 'users_group_to_perm'
954 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 954 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
955 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None ) 955 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable = False, unique = None, default = None)
956 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None ) 956 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable = False, unique = None, default = None)
957 957
958 users_group = relationship( 'UsersGroup' ) 958 users_group = relationship('UsersGroup')
959 permission = relationship( 'Permission' ) 959 permission = relationship('Permission')
960 960
961 961
962 @classmethod 962 @classmethod
963 def has_perm( cls, users_group_id, perm ): 963 def has_perm(cls, users_group_id, perm):
964 if not isinstance( perm, Permission ): 964 if not isinstance(perm, Permission):
965 raise Exception( 'perm needs to be an instance of Permission class' ) 965 raise Exception('perm needs to be an instance of Permission class')
966 966
967 return cls.query().filter( cls.users_group_id == 967 return cls.query().filter(cls.users_group_id ==
968 users_group_id )\ 968 users_group_id)\
969 .filter( cls.permission == perm )\ 969 .filter(cls.permission == perm)\
970 .scalar() is not None 970 .scalar() is not None
971 971
972 @classmethod 972 @classmethod
973 def grant_perm( cls, users_group_id, perm ): 973 def grant_perm(cls, users_group_id, perm):
974 if not isinstance( perm, Permission ): 974 if not isinstance(perm, Permission):
975 raise Exception( 'perm needs to be an instance of Permission class' ) 975 raise Exception('perm needs to be an instance of Permission class')
976 976
977 new = cls() 977 new = cls()
978 new.users_group_id = users_group_id 978 new.users_group_id = users_group_id
979 new.permission = perm 979 new.permission = perm
980 try: 980 try:
981 Session.add( new ) 981 Session.add(new)
982 Session.commit() 982 Session.commit()
983 except: 983 except:
984 Session.rollback() 984 Session.rollback()
985 985
986 986
987 @classmethod 987 @classmethod
988 def revoke_perm( cls, users_group_id, perm ): 988 def revoke_perm(cls, users_group_id, perm):
989 if not isinstance( perm, Permission ): 989 if not isinstance(perm, Permission):
990 raise Exception( 'perm needs to be an instance of Permission class' ) 990 raise Exception('perm needs to be an instance of Permission class')
991 991
992 try: 992 try:
993 cls.query().filter( cls.users_group_id == users_group_id )\ 993 cls.query().filter(cls.users_group_id == users_group_id)\
994 .filter( cls.permission == perm ).delete() 994 .filter(cls.permission == perm).delete()
995 Session.commit() 995 Session.commit()
996 except: 996 except:
997 Session.rollback() 997 Session.rollback()
998 998
999 999
1000 class GroupToPerm( Base, BaseModel ): 1000 class GroupToPerm(Base, BaseModel):
1001 __tablename__ = 'group_to_perm' 1001 __tablename__ = 'group_to_perm'
1002 __table_args__ = ( UniqueConstraint( 'group_id', 'permission_id' ), {'extend_existing':True} ) 1002 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
1003 1003
1004 group_to_perm_id = Column( "group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 1004 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
1005 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 1005 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
1006 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None ) 1006 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable = False, unique = None, default = None)
1007 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = False, unique = None, default = None ) 1007 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable = False, unique = None, default = None)
1008 1008
1009 user = relationship( 'User' ) 1009 user = relationship('User')
1010 permission = relationship( 'Permission' ) 1010 permission = relationship('Permission')
1011 group = relationship( 'Group' ) 1011 group = relationship('Group')
1012 1012
1013 class Statistics( Base, BaseModel ): 1013 class Statistics(Base, BaseModel):
1014 __tablename__ = 'statistics' 1014 __tablename__ = 'statistics'
1015 __table_args__ = ( UniqueConstraint( 'repository_id' ), {'extend_existing':True} ) 1015 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
1016 stat_id = Column( "stat_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 1016 stat_id = Column("stat_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
1017 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = True, default = None ) 1017 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable = False, unique = True, default = None)
1018 stat_on_revision = Column( "stat_on_revision", Integer(), nullable = False ) 1018 stat_on_revision = Column("stat_on_revision", Integer(), nullable = False)
1019 commit_activity = Column( "commit_activity", LargeBinary( 1000000 ), nullable = False )#JSON data 1019 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable = False)#JSON data
1020 commit_activity_combined = Column( "commit_activity_combined", LargeBinary(), nullable = False )#JSON data 1020 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable = False)#JSON data
1021 languages = Column( "languages", LargeBinary( 1000000 ), nullable = False )#JSON data 1021 languages = Column("languages", LargeBinary(1000000), nullable = False)#JSON data
1022 1022
1023 repository = relationship( 'Repository', single_parent = True ) 1023 repository = relationship('Repository', single_parent = True)
1024 1024
1025 class UserFollowing( Base, BaseModel ): 1025 class UserFollowing(Base, BaseModel):
1026 __tablename__ = 'user_followings' 1026 __tablename__ = 'user_followings'
1027 __table_args__ = ( UniqueConstraint( 'user_id', 'follows_repository_id' ), 1027 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
1028 UniqueConstraint( 'user_id', 'follows_user_id' ) 1028 UniqueConstraint('user_id', 'follows_user_id')
1029 , {'extend_existing':True} ) 1029 , {'extend_existing':True})
1030 1030
1031 user_following_id = Column( "user_following_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 1031 user_following_id = Column("user_following_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
1032 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None ) 1032 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable = False, unique = None, default = None)
1033 follows_repo_id = Column( "follows_repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = None, default = None ) 1033 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable = True, unique = None, default = None)
1034 follows_user_id = Column( "follows_user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = True, unique = None, default = None ) 1034 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable = True, unique = None, default = None)
1035 follows_from = Column( 'follows_from', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now ) 1035 follows_from = Column('follows_from', DateTime(timezone = False), nullable = True, unique = None, default = datetime.datetime.now)
1036 1036
1037 user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.user_id' ) 1037 user = relationship('User', primaryjoin = 'User.user_id==UserFollowing.user_id')
1038 1038
1039 follows_user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.follows_user_id' ) 1039 follows_user = relationship('User', primaryjoin = 'User.user_id==UserFollowing.follows_user_id')
1040 follows_repository = relationship( 'Repository', order_by = 'Repository.repo_name' ) 1040 follows_repository = relationship('Repository', order_by = 'Repository.repo_name')
1041 1041
1042 1042
1043 @classmethod 1043 @classmethod
1044 def get_repo_followers( cls, repo_id ): 1044 def get_repo_followers(cls, repo_id):
1045 return cls.query().filter( cls.follows_repo_id == repo_id ) 1045 return cls.query().filter(cls.follows_repo_id == repo_id)
1046 1046
1047 class CacheInvalidation( Base, BaseModel ): 1047 class CacheInvalidation(Base, BaseModel):
1048 __tablename__ = 'cache_invalidation' 1048 __tablename__ = 'cache_invalidation'
1049 __table_args__ = ( UniqueConstraint( 'cache_key' ), {'extend_existing':True} ) 1049 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
1050 cache_id = Column( "cache_id", Integer(), nullable = False, unique = True, default = None, primary_key = True ) 1050 cache_id = Column("cache_id", Integer(), nullable = False, unique = True, default = None, primary_key = True)
1051 cache_key = Column( "cache_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 1051 cache_key = Column("cache_key", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
1052 cache_args = Column( "cache_args", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None ) 1052 cache_args = Column("cache_args", String(length = 255, convert_unicode = False, assert_unicode = None), nullable = True, unique = None, default = None)
1053 cache_active = Column( "cache_active", Boolean(), nullable = True, unique = None, default = False ) 1053 cache_active = Column("cache_active", Boolean(), nullable = True, unique = None, default = False)
1054 1054
1055 1055
1056 def __init__( self, cache_key, cache_args = '' ): 1056 def __init__(self, cache_key, cache_args = ''):
1057 self.cache_key = cache_key 1057 self.cache_key = cache_key
1058 self.cache_args = cache_args 1058 self.cache_args = cache_args
1059 self.cache_active = False 1059 self.cache_active = False
1060 1060
1061 def __repr__( self ): 1061 def __repr__(self):
1062 return "<%s('%s:%s')>" % ( self.__class__.__name__, 1062 return "<%s('%s:%s')>" % (self.__class__.__name__,
1063 self.cache_id, self.cache_key ) 1063 self.cache_id, self.cache_key)
1064 1064
1065 class DbMigrateVersion( Base, BaseModel ): 1065 class DbMigrateVersion(Base, BaseModel):
1066 __tablename__ = 'db_migrate_version' 1066 __tablename__ = 'db_migrate_version'
1067 __table_args__ = {'extend_existing':True} 1067 __table_args__ = {'extend_existing':True}
1068 repository_id = Column( 'repository_id', String( 250 ), primary_key = True ) 1068 repository_id = Column('repository_id', String(250), primary_key = True)
1069 repository_path = Column( 'repository_path', Text ) 1069 repository_path = Column('repository_path', Text)
1070 version = Column( 'version', Integer ) 1070 version = Column('version', Integer)