1
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
16
17 from sqlalchemy import Table, Column, ForeignKey
18 from sqlalchemy.orm import relation
19
20
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
28
29
30
31
32
33
34
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
42 return "<PackageInfo name=%s>" % self.name
43
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
57 stats = property(_get_stats)
58
60 if self._releases is None:
61 self._find_releases()
62 return self._releases
63 releases = property(_get_releases)
64
66 if self._files is None:
67 self._find_releases()
68 return self._files
69 files = property(_get_files)
70
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
82 version = 'dev'
83 else:
84
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
92
93
94
95
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
116
117
118
119
120
121
122
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
173
174
175 -class Visit(object):
176 """A visit to your site."""
177
178 @classmethod
181
184 """A Visit that is link to a User object"""
185
186 pass
187
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
207
208 @classmethod
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
220 """Returns User object with given 'user_name' attribute value."""
221 return cls.query.filter_by(user_name=username).first()
222
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
230
231 try:
232 password = password.decode('utf-8')
233 except: pass
234 self._password = password
235
237 """Returns password."""
238 return self._password
239
240 password = property(_get_password, _set_password)
241
244 """A relationship that determines what each Group can do."""
245 pass
246
247
248
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