Package eggbasket :: Module model
[hide private]

Source Code for Module eggbasket.model

  1  # -*- coding: UTF-8 -*- 
  2   
  3  import os 
  4  import re 
  5   
  6  from datetime import datetime 
  7  from os.path import basename, isdir, join, getmtime, getsize 
  8   
  9  import pkg_resources 
 10  pkg_resources.require("SQLAlchemy>=0.3.10") 
 11   
 12  import turbogears as tg 
 13  from turbogears.database import metadata, mapper 
 14   
 15  # import some basic SQLAlchemy classes for declaring the data model 
 16  # (see http://www.sqlalchemy.org/docs/04/ormtutorial.html) 
 17  from sqlalchemy import Table, Column, ForeignKey 
 18  from sqlalchemy.orm import relation 
 19  # import some datatypes for table columns from SQLAlchemy 
 20  # (see http://www.sqlalchemy.org/docs/04/types.html for more) 
 21  from sqlalchemy import String, Unicode, Integer, DateTime 
 22  from sqlalchemy.exceptions import InvalidRequestError 
 23   
 24  from eggbasket.util import is_package_file 
 25  from eggbasket.pkginfo import read_pkg_info 
26 27 # your data tables 28 29 # your_table = Table('yourtable', metadata, 30 # Column('my_id', Integer, primary_key=True) 31 # ) 32 33 34 # your model classes 35 -class Package(object):
36 """A simple container class for holding information about package releases. 37 """ 38 39 _version_rx = re.compile(r'-(\d*.\d*(.\d)?)') 40
41 - def __str__(self):
42 return "<PackageInfo name=%s>" % self.name
43
44 - def __init__(self, path, name=None):
45 self.path = path 46 47 if name: 48 self.name = name 49 else: 50 self.name = basename(path) 51 self.modified = datetime.fromtimestamp(getmtime(path)) 52 self._releases = None 53 self._files = None
54
55 - def _get_stats(self):
56 return len(self.releases), sum([len(l) for l in self.files.values()])
57 stats = property(_get_stats) 58
59 - def _get_releases(self):
60 if self._releases is None: 61 self._find_releases() 62 return self._releases
63 releases = property(_get_releases) 64
65 - def _get_files(self):
66 if self._files is None: 67 self._find_releases() 68 return self._files
69 files = property(_get_files) 70
71 - def _find_releases(self):
72 self._releases = list() 73 self._files = dict() 74 known_extensions = tg.config.get('eggbasket.package_extensions', []) 75 for filename in os.listdir(self.path): 76 filepath = join(self.path, filename) 77 if isdir(filepath) or not is_package_file(filepath): 78 continue 79 80 if 'dev_' in filename: 81 # development package 82 version = 'dev' 83 else: 84 # production distribution file 85 version = None 86 mo = self._version_rx.search(filename) 87 if mo: 88 version = mo.group(1) 89 else: 90 version = u'unknown' 91 ## else: 92 ## regex = re.compile(r'-(\d*.\d*)') 93 ## mo = regex.search(filename) 94 ## if mo: 95 ## version = mo.group(1) 96 97 if not version in self._releases: 98 self._releases.append(version) 99 self._files[version] = list() 100 101 self._files[version].append( 102 dict( 103 name = filename, 104 size = getsize(filepath), 105 modified = datetime.fromtimestamp(getmtime(filepath)) 106 ) 107 ) 108 109 self._releases.sort(reverse=True) 110 self._releases.reverse() 111 self._files.get('dev', []).sort(reverse=True)
112 113 @staticmethod
114 - def package_info(filename):
115 return read_pkg_info(filename)
116 117 # set up mappers between your data tables and classes 118 119 # mapper(YourDataClass, your_table) 120 121 122 # the identity schema 123 124 visits_table = Table('visit', metadata, 125 Column('visit_key', String(40), primary_key=True), 126 Column('created', DateTime, nullable=False, default=datetime.now), 127 Column('expiry', DateTime) 128 ) 129 130 visit_identity_table = Table('visit_identity', metadata, 131 Column('visit_key', String(40), primary_key=True), 132 Column('user_id', Integer, ForeignKey('tg_user.user_id'), index=True) 133 ) 134 135 groups_table = Table('tg_group', metadata, 136 Column('group_id', Integer, primary_key=True), 137 Column('group_name', Unicode(16), unique=True), 138 Column('display_name', Unicode(255)), 139 Column('created', DateTime, default=datetime.now) 140 ) 141 142 users_table = Table('tg_user', metadata, 143 Column('user_id', Integer, primary_key=True), 144 Column('user_name', Unicode(16), unique=True), 145 Column('email_address', Unicode(255), unique=True), 146 Column('display_name', Unicode(255)), 147 Column('password', Unicode(40)), 148 Column('created', DateTime, default=datetime.now) 149 ) 150 151 permissions_table = Table('permission', metadata, 152 Column('permission_id', Integer, primary_key=True), 153 Column('permission_name', Unicode(16), unique=True), 154 Column('description', Unicode(255)) 155 ) 156 157 user_group_table = Table('user_group', metadata, 158 Column('user_id', Integer, ForeignKey('tg_user.user_id', 159 onupdate='CASCADE', ondelete='CASCADE'), primary_key=True), 160 Column('group_id', Integer, ForeignKey('tg_group.group_id', 161 onupdate='CASCADE', ondelete='CASCADE'), primary_key=True) 162 ) 163 164 group_permission_table = Table('group_permission', metadata, 165 Column('group_id', Integer, ForeignKey('tg_group.group_id', 166 onupdate='CASCADE', ondelete='CASCADE'), primary_key=True), 167 Column('permission_id', Integer, ForeignKey('permission.permission_id', 168 onupdate='CASCADE', ondelete='CASCADE'), primary_key=True) 169 )
170 171 172 # the identity model 173 174 175 -class Visit(object):
176 """A visit to your site.""" 177 178 @classmethod
179 - def lookup_visit(cls, visit_key):
180 return cls.query.get(visit_key)
181
182 183 -class VisitIdentity(object):
184 """A Visit that is link to a User object""" 185 186 pass
187
188 189 -class Group(object):
190 """An ultra-simple group definition.""" 191 192 pass
193
194 195 -class User(object):
196 """Reasonably basic User definition. 197 198 Probably would want additional attributes. 199 """ 200 201 @property
202 - def permissions(self):
203 p = set() 204 for g in self.groups: 205 p |= set(g.permissions) 206 return p
207 208 @classmethod
209 - def by_email_address(cls, email):
210 """Returns User object with given 'email_address' attribute value. 211 212 A class method that can be used to search users 213 based on their email addresses since it is unique. 214 215 """ 216 return cls.query.filter_by(email_address=email).first()
217 218 @classmethod
219 - def by_user_name(cls, username):
220 """Returns User object with given 'user_name' attribute value.""" 221 return cls.query.filter_by(user_name=username).first()
222
223 - def _set_password(self, password):
224 """Encrypts password on the fly using the encryption 225 algo defined in the configuration. 226 227 """ 228 password = tg.identity.encrypt_password(password) 229 # work around bug in identity.encrypt_password, which sometimes 230 # returns unicode, sometimes string, depending on the encryption algo 231 try: 232 password = password.decode('utf-8') 233 except: pass 234 self._password = password
235
236 - def _get_password(self):
237 """Returns password.""" 238 return self._password
239 240 password = property(_get_password, _set_password)
241
242 243 -class Permission(object):
244 """A relationship that determines what each Group can do.""" 245 pass
246 247 248 # set up mappers between identity tables and classes 249 250 mapper(Visit, visits_table) 251 252 mapper(VisitIdentity, visit_identity_table, 253 properties=dict(users=relation(User, backref='visit_identity'))) 254 255 mapper(User, users_table, 256 properties=dict(_password=users_table.c.password)) 257 258 mapper(Group, groups_table, 259 properties=dict(users=relation(User, 260 secondary=user_group_table, backref='groups'))) 261 262 mapper(Permission, permissions_table, 263 properties=dict(groups=relation(Group, 264 secondary=group_permission_table, backref='permissions'))) 265