Merge lp:~stefanor/ibid/sqlalchemy-370772 into lp:~ibid-core/ibid/old-trunk-pack-0.92
- sqlalchemy-370772
- Merge into old-trunk-pack-0.92
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Stefano Rivera | ||||||||||||
Approved revision: | 634 | ||||||||||||
Merged at revision: | 634 | ||||||||||||
Proposed branch: | lp:~stefanor/ibid/sqlalchemy-370772 | ||||||||||||
Merge into: | lp:~ibid-core/ibid/old-trunk-pack-0.92 | ||||||||||||
Diff against target: | None lines | ||||||||||||
To merge this branch: | bzr merge lp:~stefanor/ibid/sqlalchemy-370772 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Gorven | Approve | ||
Jonathan Hitchcock | Approve | ||
Review via email: mp+6141@code.launchpad.net |
This proposal supersedes a proposal from 2009-05-02.
Commit message
Description of the change
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
> We still have the option of attaching identities and accounts to the event.
> However, I'm not doing that now.
Maybe we don't. You can't reuse rolled back sessions...
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
No reviews yet, so re-submitted to get new diff
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
Note: This can't be merged until all DB-touching branches are in trunk and this has been updated to fix them too.
Also: There appears to be a bug in granting priviledges, but it'd help to have accounts-330942 merged to fix that.
Michael Gorven (mgorven) wrote : Posted in a previous version of this proposal | # |
+ self.log.
of %s plugin", processor.
Can you just change the log message so something like "Exception occured while
committing session after %s processor of %s plugin".
+ self[name] = scoped_
Do all versions of SQLAlchemy default to using transactions and autoflush?
- session.flush()
actions[
The account ID won't be available if autoflush isn't on.
There's a problem we didn't think of, which is that processors add responses
before knowing that their database changes succeeded. So the bot will still
respond positively if the commit() by the dispatcher failed. Maybe we do need
to commit() in the plugin itself.
I'd prefer the except block in Identify.identify() to only catch
IntegrityErrors.
review needs_fixing
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
> Can you just change the log message so something like "Exception occured while
> committing session after %s processor of %s plugin".
Agreed. I sort of skipped over that. r628
> Do all versions of SQLAlchemy default to using transactions and autoflush?
All supported versions. And not likely to change.
> The account ID won't be available if autoflush isn't on.
No, autoflush doesn't help, but yes we do need a manual flush. r629
Although logging factoid IDs is of arguable value.
> There's a problem we didn't think of, which is that processors add responses
> before knowing that their database changes succeeded. So the bot will still
> respond positively if the commit() by the dispatcher failed. Maybe we do need
> to commit() in the plugin itself.
Yes, that's certainly an issue. We even have the option of re-running failed
processors now (although we'd need to differentiate which are safe to re-run,
etc.)
> I'd prefer the except block in Identify.identify() to only catch
> IntegrityErrors.
Agreed. r631
The reason for that is SQLite can cause an OperationalError to be thrown if
the database is locked. The correct behaviour in that case is probably to sleep
and then try and commit again. (at least at the pysqlite level, that'd be the
right thing)
Jonathan Hitchcock (vhata) : | # |
- 633. By Stefano Rivera
-
Merge from trunk
Michael Gorven (mgorven) wrote : | # |
This still allows positive acknowledgements to be returned even if the
commit() fails. If we need to flush() in order to get an ID for logging, why
don't we just commit() instead? As long as the dispatcher cleans up the
session when commit() fails, I don't see a problem.
- 634. By Stefano Rivera
-
Commit in plugins, to ensure that Ibid only confirms successful actions (rollback in dispatcher)
Stefano Rivera (stefanor) wrote : | # |
r634
Michael Gorven (mgorven) wrote : | # |
Why is the session deleted if an exception occurs? Is rolling back not
sufficient?
Stefano Rivera (stefanor) wrote : | # |
> Why is the session deleted if an exception occurs? Is rolling back not
> sufficient?
Exactly, you can't operate on a rolled back sqlalchemy session.
Michael Gorven (mgorven) wrote : | # |
> Exactly, you can't operate on a rolled back sqlalchemy session.
Um, I don't understand why that should be the case, but okay.
review approve
Preview Diff
1 | === modified file 'ibid/auth.py' |
2 | --- ibid/auth.py 2009-03-16 21:00:23 +0000 |
3 | +++ ibid/auth.py 2009-05-02 22:05:13 +0000 |
4 | @@ -23,11 +23,11 @@ |
5 | salt = ''.join([choice(chars) for i in xrange(8)]) |
6 | return unicode(salt + sha1(salt + password).hexdigest()) |
7 | |
8 | -def permission(name, account, source): |
9 | +def permission(name, account, source, session): |
10 | if account: |
11 | - session = ibid.databases.ibid() |
12 | - permission = session.query(Permission).filter_by(account_id=account).filter_by(name=name).first() |
13 | - session.close() |
14 | + permission = session.query(Permission) \ |
15 | + .filter_by(account_id=account) \ |
16 | + .filter_by(name=name).first() |
17 | |
18 | if permission: |
19 | return permission.value |
20 | @@ -95,7 +95,7 @@ |
21 | return False |
22 | |
23 | def authorise(self, event, name): |
24 | - value = permission(name, event.account, event.source) |
25 | + value = permission(name, event.account, event.source, event.session) |
26 | self.log.info(u"Checking %s permission for %s/%s (%s): %s", name, event.account, event.identity, event.sender['connection'], value) |
27 | |
28 | if value == 'yes': |
29 | @@ -105,15 +105,17 @@ |
30 | |
31 | return False |
32 | |
33 | - def implicit(self, event, credential = None): |
34 | + def implicit(self, event, credential=None): |
35 | return True |
36 | |
37 | def password(self, event, password): |
38 | if password is None: |
39 | return False |
40 | |
41 | - session = ibid.databases.ibid() |
42 | - for credential in session.query(Credential).filter_by(method=u'password').filter_by(account_id=event.account).filter(or_(Credential.source == event.source, Credential.source == None)).all(): |
43 | + for credential in event.session.query(Credential) \ |
44 | + .filter_by(method=u'password') \ |
45 | + .filter_by(account_id=event.account) \ |
46 | + .filter(or_(Credential.source == event.source, Credential.source == None)).all(): |
47 | if hash(password, credential.credential) == credential.credential: |
48 | return True |
49 | |
50 | |
51 | === modified file 'ibid/core.py' |
52 | --- ibid/core.py 2009-05-02 15:14:56 +0000 |
53 | +++ ibid/core.py 2009-05-03 16:37:03 +0000 |
54 | @@ -7,6 +7,7 @@ |
55 | from twisted.python.modules import getModule |
56 | from sqlalchemy import create_engine |
57 | from sqlalchemy.orm import sessionmaker, scoped_session |
58 | +from sqlalchemy.exceptions import IntegrityError |
59 | |
60 | import ibid |
61 | import auth |
62 | @@ -21,9 +22,25 @@ |
63 | try: |
64 | processor.process(event) |
65 | except Exception: |
66 | - self.log.exception(u"Exception occured in %s processor of %s plugin", processor.__class__.__name__, processor.name) |
67 | + self.log.exception(u"Exception occured in %s processor of %s plugin", |
68 | + processor.__class__.__name__, processor.name) |
69 | event.complain = u'exception' |
70 | |
71 | + if 'session' in event and (event.session.dirty or event.session.deleted): |
72 | + try: |
73 | + event.session.commit() |
74 | + except IntegrityError: |
75 | + self.log.exception(u"Exception occured committing session from the %s processor of %s plugin", |
76 | + processor.__class__.__name__, processor.name) |
77 | + event.complain = u'exception' |
78 | + event.session.rollback() |
79 | + event.session.close() |
80 | + del event['session'] |
81 | + |
82 | + if 'session' in event: |
83 | + event.session.close() |
84 | + del event['session'] |
85 | + |
86 | log_level = logging.DEBUG |
87 | if event.type == u'clock' and not event.processed: |
88 | log_level -= 5 |
89 | @@ -263,7 +280,7 @@ |
90 | |
91 | engine.dialect.use_ansiquotes = True |
92 | |
93 | - self[name] = scoped_session(sessionmaker(bind=engine, transactional=False, autoflush=True)) |
94 | + self[name] = scoped_session(sessionmaker(bind=engine)) |
95 | |
96 | self.log.info(u"Loaded %s database", name) |
97 | |
98 | |
99 | === modified file 'ibid/event.py' |
100 | --- ibid/event.py 2009-05-01 11:14:06 +0000 |
101 | +++ ibid/event.py 2009-05-02 19:29:44 +0000 |
102 | @@ -1,3 +1,4 @@ |
103 | +import ibid |
104 | |
105 | class Event(dict): |
106 | |
107 | @@ -9,6 +10,8 @@ |
108 | self.processed = False |
109 | |
110 | def __getattr__(self, name): |
111 | + if name == 'session' and 'session' not in self: |
112 | + self['session'] = ibid.databases.ibid() |
113 | return self[name] |
114 | |
115 | def __setattr__(self, name, value): |
116 | |
117 | === modified file 'ibid/models.py' |
118 | --- ibid/models.py 2009-04-21 20:09:06 +0000 |
119 | +++ ibid/models.py 2009-05-02 19:29:44 +0000 |
120 | @@ -61,7 +61,6 @@ |
121 | metadata.tables[dependancy].versioned_schema.upgrade_schema(sessionmaker) |
122 | |
123 | self.upgrade_session = session = sessionmaker() |
124 | - trans = session.begin() |
125 | |
126 | schema = session.query(Schema).filter(Schema.table==unicode(self.table.name)).first() |
127 | |
128 | @@ -79,8 +78,7 @@ |
129 | for version in range(schema.version + 1, self.version + 1): |
130 | log.info(u"Upgrading table %s to version %i", self.table.name, version) |
131 | |
132 | - trans.commit() |
133 | - trans = session.begin() |
134 | + session.commit() |
135 | |
136 | getattr(self, 'upgrade_%i_to_%i' % (version - 1, version))() |
137 | |
138 | @@ -88,10 +86,10 @@ |
139 | session.save_or_update(schema) |
140 | del self.upgrade_reflected_model |
141 | |
142 | - trans.commit() |
143 | + session.commit() |
144 | |
145 | except: |
146 | - trans.rollback() |
147 | + session.rollback() |
148 | raise |
149 | |
150 | session.close() |
151 | @@ -236,7 +234,7 @@ |
152 | schema = Schema(unicode(self.table.name), self.version) |
153 | session.save_or_update(schema) |
154 | |
155 | - session.flush() |
156 | + session.commit() |
157 | session.close() |
158 | |
159 | __table__.versioned_schema = SchemaSchema(__table__, 1) |
160 | |
161 | === modified file 'ibid/plugins/auth.py' |
162 | --- ibid/plugins/auth.py 2009-05-01 12:22:37 +0000 |
163 | +++ ibid/plugins/auth.py 2009-05-03 16:25:57 +0000 |
164 | @@ -5,7 +5,7 @@ |
165 | import ibid |
166 | from ibid.plugins import Processor, match, auth_responses, authorise |
167 | from ibid.models import Credential, Permission, Account |
168 | -from ibid.auth import hash, permission |
169 | +from ibid.auth import hash |
170 | |
171 | help = {} |
172 | |
173 | @@ -21,7 +21,6 @@ |
174 | @match(r'^authenticate\s+(.+?)(?:\s+on\s+(.+))?\s+using\s+(\S+)\s+(.+)$') |
175 | def handler(self, event, user, source, method, credential): |
176 | |
177 | - session = ibid.databases.ibid() |
178 | if user.lower() == 'me': |
179 | if not event.account: |
180 | event.addresponse(u"I don't know who you are") |
181 | @@ -29,15 +28,14 @@ |
182 | if not ibid.auth.authenticate(event): |
183 | event.complain = 'notauthed' |
184 | return |
185 | - account = session.query(Account).filter_by(id=event.account).first() |
186 | + account = event.session.query(Account).filter_by(id=event.account).first() |
187 | |
188 | else: |
189 | if not auth_responses(event, 'admin'): |
190 | return |
191 | - account = session.query(Account).filter_by(username=user).first() |
192 | + account = event.session.query(Account).filter_by(username=user).first() |
193 | if not account: |
194 | event.addresponse(u"I don't know who %s is", user) |
195 | - session.close() |
196 | return |
197 | |
198 | if source: |
199 | @@ -49,14 +47,15 @@ |
200 | if method.lower() == 'password': |
201 | password = hash(credential) |
202 | event.message['clean'] = event.message['clean'][:-len(credential)] + password |
203 | - event.message['raw'] = event.message['raw'][:event.message['raw'].rfind(credential)] + password + event.message['raw'][event.message['raw'].rfind(credential)+len(credential):] |
204 | + event.message['raw'] = event.message['raw'][:event.message['raw'].rfind(credential)] \ |
205 | + + password + event.message['raw'][event.message['raw'].rfind(credential)+len(credential):] |
206 | credential = password |
207 | |
208 | credential = Credential(method, credential, source, account.id) |
209 | - session.save_or_update(credential) |
210 | - session.flush() |
211 | - log.info(u"Added %s credential %s for account %s (%s) on %s by account %s", method, credential.credential, account.id, account.username, source, event.account) |
212 | - session.close() |
213 | + event.session.save_or_update(credential) |
214 | + event.session.flush() |
215 | + log.info(u"Added %s credential %s for account %s (%s) on %s by account %s", |
216 | + method, credential.credential, account.id, account.username, source, event.account) |
217 | |
218 | event.addresponse(True) |
219 | |
220 | @@ -73,17 +72,17 @@ |
221 | @authorise |
222 | def grant(self, event, action, name, username, auth): |
223 | |
224 | - session = ibid.databases.ibid() |
225 | - account = session.query(Account).filter_by(username=username).first() |
226 | + account = event.session.query(Account).filter_by(username=username).first() |
227 | if not account: |
228 | event.addresponse(u"I don't know who %s is", username) |
229 | - session.close() |
230 | return |
231 | |
232 | - permission = session.query(Permission).filter_by(account_id=account.id).filter(func.lower(Permission.name)==name.lower()).first() |
233 | + permission = event.session.query(Permission) \ |
234 | + .filter_by(account_id=account.id) \ |
235 | + .filter(func.lower(Permission.name) == name.lower()).first() |
236 | if action.lower() == 'remove': |
237 | if permission: |
238 | - session.delete(permission) |
239 | + event.session.delete(permission) |
240 | else: |
241 | event.addresponse(u"%s doesn't have that permission anyway", username) |
242 | return |
243 | @@ -108,26 +107,25 @@ |
244 | return |
245 | |
246 | permission.value = value |
247 | - session.save_or_update(permission) |
248 | + event.session.save_or_update(permission) |
249 | |
250 | - session.flush() |
251 | - log.info(u"%s %s permission for account %s (%s) by account %s", actions[action.lower()], name, account.id, account.username, event.account) |
252 | - session.close() |
253 | + event.session.flush() |
254 | + log.info(u"%s %s permission for account %s (%s) by account %s", |
255 | + actions[action.lower()], name, account.id, account.username, event.account) |
256 | |
257 | event.addresponse(True) |
258 | |
259 | @match(r'^permissions(?:\s+for\s+(\S+))?$') |
260 | def list(self, event, username): |
261 | - session = ibid.databases.ibid() |
262 | if not username: |
263 | if not event.account: |
264 | event.addresponse(u"I don't know who you are") |
265 | return |
266 | - account = session.query(Account).filter_by(id=event.account).first() |
267 | + account = event.session.query(Account).filter_by(id=event.account).first() |
268 | else: |
269 | if not auth_responses(event, u'accounts'): |
270 | return |
271 | - account = session.query(Account).filter_by(username=username).first() |
272 | + account = event.session.query(Account).filter_by(username=username).first() |
273 | if not account: |
274 | event.addresponse(u"I don't know who %s is", username) |
275 | return |
276 | |
277 | === modified file 'ibid/plugins/factoid.py' |
278 | --- ibid/plugins/factoid.py 2009-05-01 12:17:57 +0000 |
279 | +++ ibid/plugins/factoid.py 2009-05-03 16:33:10 +0000 |
280 | @@ -6,7 +6,6 @@ |
281 | from sqlalchemy.orm import relation, eagerload |
282 | from sqlalchemy.sql import func |
283 | |
284 | -import ibid |
285 | from ibid.plugins import Processor, match, handler, authorise, auth_responses, RPC |
286 | from ibid.config import Option, IntOption |
287 | from ibid.plugins.identity import get_identities |
288 | @@ -160,9 +159,7 @@ |
289 | |
290 | @match(r'^literal\s+(.+?)(?:\s+#(\d+)|\s+(?:/(.+?)/(r?)))?$') |
291 | def literal(self, event, name, number, pattern, is_regex): |
292 | - session = ibid.databases.ibid() |
293 | - factoids = get_factoid(session, name, number, pattern, is_regex, literal=True) |
294 | - session.close() |
295 | + factoids = get_factoid(event.session, name, number, pattern, is_regex, literal=True) |
296 | number = number and int(number) or 0 |
297 | if factoids: |
298 | event.addresponse(u', '.join(u'%i: %s' |
299 | @@ -179,12 +176,11 @@ |
300 | @match(r'^forget\s+(.+?)(?:\s+#(\d+)|\s+(?:/(.+?)/(r?)))?$') |
301 | @authorise |
302 | def forget(self, event, name, number, pattern, is_regex): |
303 | - session = ibid.databases.ibid() |
304 | - factoids = get_factoid(session, name, number, pattern, is_regex, all=True) |
305 | + factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True) |
306 | if factoids: |
307 | factoidadmin = auth_responses(event, u'factoidadmin') |
308 | - identities = get_identities(event, session) |
309 | - factoid = session.query(Factoid).get(factoids[0][0].id) |
310 | + identities = get_identities(event) |
311 | + factoid = event.session.query(Factoid).get(factoids[0][0].id) |
312 | |
313 | if (number or pattern): |
314 | if len(factoids) > 1: |
315 | @@ -194,30 +190,28 @@ |
316 | if factoids[0][2].identity_id not in identities and not factoidadmin: |
317 | return |
318 | |
319 | - if session.query(FactoidValue).filter_by(factoid_id=factoid.id).count() == 1: |
320 | + if event.session.query(FactoidValue).filter_by(factoid_id=factoid.id).count() == 1: |
321 | if len(filter(lambda x: x.identity_id not in identities, factoid.names)) > 0 and not factoidadmin: |
322 | return |
323 | log.info(u"Deleting factoid %s (%s) by %s/%s (%s)", factoid.id, name, event.account, event.identity, event.sender['connection']) |
324 | - session.delete(factoid) |
325 | + event.session.delete(factoid) |
326 | else: |
327 | log.info(u"Deleting value %s of factoid %s (%s) by %s/%s (%s)", factoids[0][2].id, factoid.id, factoids[0][2].value, event.account, event.identity, event.sender['connection']) |
328 | - session.delete(factoids[0][2]) |
329 | + event.session.delete(factoids[0][2]) |
330 | |
331 | else: |
332 | if factoids[0][1].identity_id not in identities and not factoidadmin: |
333 | return |
334 | |
335 | - if session.query(FactoidName).filter_by(factoid_id=factoid.id).count() == 1: |
336 | + if event.session.query(FactoidName).filter_by(factoid_id=factoid.id).count() == 1: |
337 | if len(filter(lambda x: x.identity_id not in identities, factoid.values)) > 0 and not factoidadmin: |
338 | return |
339 | log.info(u"Deleting factoid %s (%s) by %s/%s (%s)", factoid.id, name, event.account, event.identity, event.sender['connection']) |
340 | - session.delete(factoid) |
341 | + event.session.delete(factoid) |
342 | else: |
343 | log.info(u"Deleting name %s of factoid %s (%s) by %s/%s (%s)", factoids[0][1].id, factoid.id, factoids[0][1].name, event.account, event.identity, event.sender['connection']) |
344 | - session.delete(factoids[0][1]) |
345 | + event.session.delete(factoids[0][1]) |
346 | |
347 | - session.flush() |
348 | - session.close() |
349 | event.addresponse(True) |
350 | else: |
351 | event.addresponse(u"I didn't know about %s anyway", name) |
352 | @@ -230,15 +224,12 @@ |
353 | event.addresponse(u"That makes no sense, they *are* the same") |
354 | return |
355 | |
356 | - session = ibid.databases.ibid() |
357 | - factoid = session.query(Factoid).join(Factoid.names)\ |
358 | + factoid = event.session.query(Factoid).join(Factoid.names)\ |
359 | .filter(func.lower(FactoidName.name)==escape_name(source).lower()).first() |
360 | if factoid: |
361 | name = FactoidName(escape_name(unicode(target)), event.identity) |
362 | factoid.names.append(name) |
363 | - session.save_or_update(factoid) |
364 | - session.flush() |
365 | - session.close() |
366 | + event.session.save_or_update(factoid) |
367 | event.addresponse(True) |
368 | log.info(u"Added name '%s' to factoid %s by %s/%s (%s)", name.name, factoid.id, event.account, event.identity, event.sender['connection']) |
369 | else: |
370 | @@ -266,8 +257,7 @@ |
371 | pattern = m.group(1) |
372 | is_regex = bool(m.group(2)) |
373 | |
374 | - session = ibid.databases.ibid() |
375 | - query = session.query(Factoid)\ |
376 | + query = event.session.query(Factoid)\ |
377 | .join(Factoid.names).add_entity(FactoidName)\ |
378 | .join(Factoid.values) |
379 | |
380 | @@ -320,9 +310,7 @@ |
381 | event.addresponse(response) |
382 | |
383 | def remote_get(self, name, number=None, pattern=None, is_regex=None, event={}): |
384 | - session = ibid.databases.ibid() |
385 | - factoid = get_factoid(session, name, number, pattern, is_regex) |
386 | - session.close() |
387 | + factoid = get_factoid(event.session, name, number, pattern, is_regex) |
388 | |
389 | if factoid: |
390 | (factoid, fname, fvalue) = factoid |
391 | @@ -377,17 +365,15 @@ |
392 | def set_factoid(self, event, correction, name, verb1, verb2, addition, value): |
393 | verb = verb1 and verb1 or verb2 |
394 | |
395 | - session = ibid.databases.ibid() |
396 | - factoid = session.query(Factoid).join(Factoid.names)\ |
397 | + factoid = event.session.query(Factoid).join(Factoid.names)\ |
398 | .filter(func.lower(FactoidName.name)==escape_name(name).lower()).first() |
399 | if factoid: |
400 | if correction: |
401 | - identities = get_identities(event, session) |
402 | + identities = get_identities(event) |
403 | if not auth_responses(event, u'factoidadmin') and len(filter(lambda x: x.identity_id not in identities, factoid.values)) > 0: |
404 | return |
405 | for fvalue in factoid.values: |
406 | - session.delete(fvalue) |
407 | - session.flush() |
408 | + event.session.delete(fvalue) |
409 | elif not addition: |
410 | event.addresponse(u'I already know stuff about %s', name) |
411 | return |
412 | @@ -395,6 +381,7 @@ |
413 | factoid = Factoid() |
414 | fname = FactoidName(escape_name(unicode(name)), event.identity) |
415 | factoid.names.append(fname) |
416 | + event.session.flush() |
417 | log.info(u"Created factoid %s with name '%s' by %s", factoid.id, fname.name, event.identity) |
418 | |
419 | if not reply_re.match(value) and not action_re.match(value): |
420 | @@ -402,9 +389,7 @@ |
421 | fvalue = FactoidValue(unicode(value), event.identity) |
422 | factoid.values.append(fvalue) |
423 | log.info(u"Added value '%s' to factoid %s by %s/%s (%s)", fvalue.value, factoid.id, event.account, event.identity, event.sender['connection']) |
424 | - session.save_or_update(factoid) |
425 | - session.flush() |
426 | - session.close() |
427 | + event.session.save_or_update(factoid) |
428 | event.addresponse(True) |
429 | |
430 | class Modify(Processor): |
431 | @@ -419,8 +404,7 @@ |
432 | @match(r'^(.+?)(?:\s+#(\d+)|\s+/(.+?)/(r?))?\s*\+=\s?(.+)$') |
433 | @authorise |
434 | def append(self, event, name, number, pattern, is_regex, suffix): |
435 | - session = ibid.databases.ibid() |
436 | - factoids = get_factoid(session, name, number, pattern, is_regex, all=True) |
437 | + factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True) |
438 | if len(factoids) == 0: |
439 | if pattern: |
440 | event.addresponse(u"I don't know about any %(name)s matching %(pattern)s", { |
441 | @@ -433,7 +417,7 @@ |
442 | event.addresponse(u"Pattern matches multiple factoids, please be more specific") |
443 | else: |
444 | factoidadmin = auth_responses(event, u'factoidadmin') |
445 | - identities = get_identities(event, session) |
446 | + identities = get_identities(event) |
447 | factoid = factoids[0] |
448 | |
449 | if factoid[2].identity_id not in identities and not factoidadmin: |
450 | @@ -443,16 +427,13 @@ |
451 | suffix, factoid[2].id, factoid[0].id, factoid[2].value, event.account, event.identity, event.sender['connection']) |
452 | factoid[2].value += suffix |
453 | |
454 | - session.save_or_update(factoid[2]) |
455 | - session.flush() |
456 | - session.close() |
457 | + event.session.save_or_update(factoid[2]) |
458 | event.addresponse(True) |
459 | |
460 | @match(r'^(.+?)(?:\s+#(\d+)|\s+/(.+?)/(r?))?\s*(?:~=|=~)\s*([sy](?P<sep>.).+(?P=sep).*(?P=sep)[gir]*)$') |
461 | @authorise |
462 | def modify(self, event, name, number, pattern, is_regex, operation, separator): |
463 | - session = ibid.databases.ibid() |
464 | - factoids = get_factoid(session, name, number, pattern, is_regex, all=True) |
465 | + factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True) |
466 | if len(factoids) == 0: |
467 | if pattern: |
468 | event.addresponse(u"I don't know about any %(name)s matching %(pattern)s", { |
469 | @@ -465,7 +446,7 @@ |
470 | event.addresponse(u"Pattern matches multiple factoids, please be more specific") |
471 | else: |
472 | factoidadmin = auth_responses(event, u'factoidadmin') |
473 | - identities = get_identities(event, session) |
474 | + identities = get_identities(event) |
475 | factoid = factoids[0] |
476 | |
477 | if factoid[2].identity_id not in identities and not factoidadmin: |
478 | @@ -537,9 +518,7 @@ |
479 | log.info(u"Applying '%s' to value %s of factoid %s (%s) by %s/%s (%s)", |
480 | operation, factoid[2].id, factoid[0].id, oldvalue, event.account, event.identity, event.sender['connection']) |
481 | |
482 | - session.save_or_update(factoid[2]) |
483 | - session.flush() |
484 | - session.close() |
485 | + event.session.save_or_update(factoid[2]) |
486 | event.addresponse(True) |
487 | |
488 | # vi: set et sta sw=4 ts=4: |
489 | |
490 | === modified file 'ibid/plugins/feeds.py' |
491 | --- ibid/plugins/feeds.py 2009-05-01 12:17:57 +0000 |
492 | +++ ibid/plugins/feeds.py 2009-05-03 16:33:10 +0000 |
493 | @@ -10,7 +10,6 @@ |
494 | import feedparser |
495 | from html2text import html2text_file |
496 | |
497 | -import ibid |
498 | from ibid.plugins import Processor, match, authorise |
499 | from ibid.models import Base, VersionedSchema |
500 | from ibid.utils import cacheable_download, get_html_parse_tree |
501 | @@ -56,8 +55,8 @@ |
502 | @match(r'^add\s+feed\s+(.+?)\s+as\s+(.+?)$') |
503 | @authorise |
504 | def add(self, event, url, name): |
505 | - session = ibid.databases.ibid() |
506 | - feed = session.query(Feed).filter(func.lower(Feed.name)==name.lower()).first() |
507 | + feed = event.session.query(Feed) \ |
508 | + .filter(func.lower(Feed.name) == name.lower()).first() |
509 | |
510 | if feed: |
511 | event.addresponse(u"I already have the %s feed", name) |
512 | @@ -85,15 +84,13 @@ |
513 | return |
514 | |
515 | feed = Feed(unicode(name), unicode(url), event.identity) |
516 | - session.save(feed) |
517 | - session.flush() |
518 | + event.session.save(feed) |
519 | event.addresponse(True) |
520 | log.info(u"Added feed '%s' by %s/%s (%s): %s (Found %s entries)", name, event.account, event.identity, event.sender['connection'], url, len(feed.entries)) |
521 | |
522 | @match(r'^(?:list\s+)?feeds$') |
523 | def list(self, event): |
524 | - session = ibid.databases.ibid() |
525 | - feeds = session.query(Feed).all() |
526 | + feeds = event.session.query(Feed).all() |
527 | if feeds: |
528 | event.addresponse(u'I know about: %s', u', '.join(sorted([feed.name for feed in feeds]))) |
529 | else: |
530 | @@ -102,19 +99,16 @@ |
531 | @match(r'^remove\s+(.+?)\s+feed$') |
532 | @authorise |
533 | def remove(self, event, name): |
534 | - session = ibid.databases.ibid() |
535 | - feed = session.query(Feed).filter(func.lower(Feed.name)==name.lower()).first() |
536 | + feed = event.session.query(Feed) \ |
537 | + .filter(func.lower(Feed.name) == name.lower()).first() |
538 | |
539 | if not feed: |
540 | event.addresponse(u"I don't have the %s feed anyway", name) |
541 | else: |
542 | - session.delete(feed) |
543 | + event.session.delete(feed) |
544 | log.info(u"Deleted feed '%s' by %s/%s (%s): %s", name, event.account, event.identity, event.sender['connection'], feed.url) |
545 | - session.flush() |
546 | event.addresponse(True) |
547 | |
548 | - session.close() |
549 | - |
550 | class Retrieve(Processor): |
551 | u"""latest [ <count> ] articles from <name> [ starting at <number> ] |
552 | article ( <number> | /<pattern>/ ) from <name>""" |
553 | @@ -125,9 +119,8 @@ |
554 | number = number and int(number) or 10 |
555 | start = start and int(start) or 0 |
556 | |
557 | - session = ibid.databases.ibid() |
558 | - feed = session.query(Feed).filter(func.lower(Feed.name)==name.lower()).first() |
559 | - session.close() |
560 | + feed = event.session.query(Feed) \ |
561 | + .filter(func.lower(Feed.name) == name.lower()).first() |
562 | |
563 | if not feed: |
564 | event.addresponse(u"I don't know about the %s feed", name) |
565 | @@ -144,9 +137,8 @@ |
566 | |
567 | @match(r'^article\s+(?:(\d+)|/(.+?)/)\s+from\s+(.+?)$') |
568 | def article(self, event, number, pattern, name): |
569 | - session = ibid.databases.ibid() |
570 | - feed = session.query(Feed).filter(func.lower(Feed.name)==name.lower()).first() |
571 | - session.close() |
572 | + feed = event.session.query(Feed) \ |
573 | + .filter(func.lower(Feed.name) == name.lower()).first() |
574 | |
575 | if not feed: |
576 | event.addresponse(u"I don't know about the %s feed", name) |
577 | |
578 | === modified file 'ibid/plugins/identity.py' |
579 | --- ibid/plugins/identity.py 2009-04-27 00:50:19 +0000 |
580 | +++ ibid/plugins/identity.py 2009-05-03 16:37:03 +0000 |
581 | @@ -15,43 +15,45 @@ |
582 | |
583 | log = logging.getLogger('plugins.identity') |
584 | |
585 | -help['accounts'] = u'An account represents a person. An account has one or more identities, which is a user on a specific source.' |
586 | +help['accounts'] = u'An account represents a person. ' \ |
587 | + 'An account has one or more identities, which is a user on a specific source.' |
588 | class Accounts(Processor): |
589 | u"""create account <name>""" |
590 | feature = 'accounts' |
591 | |
592 | @match(r'^create\s+account\s+(.+)$') |
593 | def account(self, event, username): |
594 | - session = ibid.databases.ibid() |
595 | admin = False |
596 | |
597 | if event.account: |
598 | if ibid.auth.authenticate(event) and ibid.auth.authorise(event, 'accounts'): |
599 | admin = True |
600 | else: |
601 | - account = session.query(Account).filter_by(id=event.account).first() |
602 | + account = event.session.query(Account).filter_by(id=event.account).first() |
603 | event.addresponse(u'You already have an account called "%s"', account.username) |
604 | return |
605 | |
606 | - account = session.query(Account).filter_by(username=username).first() |
607 | + account = event.session.query(Account).filter_by(username=username).first() |
608 | if account: |
609 | - event.addresponse(u'There is already an account called "%s". Please choose a different name', account.username) |
610 | + event.addresponse(u'There is already an account called "%s". ' \ |
611 | + 'Please choose a different name', account.username) |
612 | return |
613 | |
614 | account = Account(username) |
615 | - session.save_or_update(account) |
616 | - session.flush() |
617 | - log.info(u"Created account %s (%s) by %s/%s (%s)", account.id, account.username, event.account, event.identity, event.sender['connection']) |
618 | + event.session.save_or_update(account) |
619 | + event.session.flush() |
620 | + log.info(u"Created account %s (%s) by %s/%s (%s)", |
621 | + account.id, account.username, event.account, event.identity, event.sender['connection']) |
622 | |
623 | if not admin: |
624 | - identity = session.query(Identity).filter_by(id=event.identity).first() |
625 | + identity = event.session.query(Identity).filter_by(id=event.identity).first() |
626 | identity.account_id = account.id |
627 | session.save_or_update(identity) |
628 | - session.flush() |
629 | - log.info(u"Attached identity %s (%s on %s) to account %s (%s)", identity.id, identity.identity, identity.source, account.id, account.username) |
630 | + event.session.flush() |
631 | + log.info(u"Attached identity %s (%s on %s) to account %s (%s)", |
632 | + identity.id, identity.identity, identity.source, account.id, account.username) |
633 | |
634 | identify_cache.clear() |
635 | - session.close() |
636 | event.addresponse(True) |
637 | |
638 | chars = string.letters + string.digits |
639 | @@ -68,44 +70,54 @@ |
640 | |
641 | @match(r'^(I|.+?)\s+(?:is|am)\s+(.+)\s+on\s+(.+)$') |
642 | def identity(self, event, username, identity, source): |
643 | - session = ibid.databases.ibid() |
644 | admin = False |
645 | identity = identity.replace(' ', '') |
646 | |
647 | if username.upper() == 'I': |
648 | if event.account: |
649 | - account = session.query(Account).filter_by(id=event.account).first() |
650 | + account = event.session.query(Account).filter_by(id=event.account).first() |
651 | else: |
652 | username = event.sender['id'] |
653 | - account = session.query(Account).filter_by(username=username).first() |
654 | + |
655 | + account = event.session.query(Account).filter_by(username=username).first() |
656 | + |
657 | if account: |
658 | event.addresponse(u'I tried to create the account %s for you, but it already exists. ' |
659 | u"Please use 'create account <name>'", username) |
660 | return |
661 | + |
662 | account = Account(username) |
663 | - session.save_or_update(account) |
664 | - session.flush() |
665 | - currentidentity = session.query(Identity).filter_by(id=event.identity).first() |
666 | + event.session.save_or_update(account) |
667 | + |
668 | + currentidentity = event.session.query(Identity).filter_by(id=event.identity).first() |
669 | currentidentity.account_id = account.id |
670 | - session.save_or_update(currentidentity) |
671 | - session.flush() |
672 | + event.session.save_or_update(currentidentity) |
673 | + |
674 | identify_cache.clear() |
675 | + |
676 | event.addresponse(u"I've created the account %s for you", username) |
677 | - log.info(u"Created account %s (%s) by %s/%s (%s)", account.id, account.username, event.account, event.identity, event.sender['connection']) |
678 | - log.info(u"Attached identity %s (%s on %s) to account %s (%s)", currentidentity.id, currentidentity.identity, currentidentity.source, account.id, account.username) |
679 | + |
680 | + event.session.flush() |
681 | + log.info(u"Created account %s (%s) by %s/%s (%s)", |
682 | + account.id, account.username, event.account, event.identity, event.sender['connection']) |
683 | + log.info(u"Attached identity %s (%s on %s) to account %s (%s)", |
684 | + currentidentity.id, currentidentity.identity, currentidentity.source, account.id, account.username) |
685 | |
686 | else: |
687 | if not auth_responses(event, 'accounts'): |
688 | return |
689 | admin = True |
690 | - account = session.query(Account).filter_by(username=username).first() |
691 | + account = event.session.query(Account).filter_by(username=username).first() |
692 | if not account: |
693 | event.addresponse(u"I don't know who %s is", username) |
694 | return |
695 | |
696 | - ident = session.query(Identity).filter(func.lower(Identity.identity)==identity.lower()).filter(func.lower(Identity.source)==source.lower()).first() |
697 | + ident = event.session.query(Identity) \ |
698 | + .filter(func.lower(Identity.identity) == identity.lower()) \ |
699 | + .filter(func.lower(Identity.source) == source.lower()).first() |
700 | if ident and ident.account: |
701 | - event.addresponse(u'This identity is already attached to account %s', ident.account.username) |
702 | + event.addresponse(u'This identity is already attached to account %s', |
703 | + ident.account.username) |
704 | return |
705 | |
706 | if source not in ibid.sources: |
707 | @@ -121,22 +133,26 @@ |
708 | if event.public: |
709 | response['target'] = event.sender['id'] |
710 | event.addresponse(response) |
711 | - log.info(u"Sent token %s to %s/%s (%s)", token, event.account, event.identity, event.sender['connection']) |
712 | + log.info(u"Sent token %s to %s/%s (%s)", |
713 | + token, event.account, event.identity, event.sender['connection']) |
714 | |
715 | else: |
716 | if not ident: |
717 | ident = Identity(source, identity) |
718 | ident.account_id = account.id |
719 | - session.save_or_update(ident) |
720 | - session.flush() |
721 | + event.session.save_or_update(ident) |
722 | + |
723 | identify_cache.clear() |
724 | event.addresponse(True) |
725 | - log.info(u"Attached identity %s (%s on %s) to account %s (%s) by %s/%s (%s)", ident.id, ident.identity, ident.source, account.id, account.username, event.account, event.identity, event.sender['connection']) |
726 | + |
727 | + event.session.flush() |
728 | + log.info(u"Attached identity %s (%s on %s) to account %s (%s) by %s/%s (%s)", |
729 | + ident.id, ident.identity, ident.source, account.id, account.username, |
730 | + event.account, event.identity, event.sender['connection']) |
731 | |
732 | @match(r'^(\S{16})$') |
733 | def token(self, event, token): |
734 | if token in self.tokens: |
735 | - session = ibid.databases.ibid() |
736 | (account_id, user, source) = self.tokens[token] |
737 | if event.source.lower() != source.lower() or event.sender['id'].lower() != user.lower(): |
738 | event.addresponse(u'You need to send me this token from %(name)s on %(source)s', { |
739 | @@ -145,45 +161,49 @@ |
740 | }) |
741 | return |
742 | |
743 | - identity = session.query(Identity).filter(func.lower(Identity.identity)==user.lower()).filter(func.lower(Identity.source)==source.lower()).first() |
744 | + identity = event.session.query(Identity) \ |
745 | + .filter(func.lower(Identity.identity) == user.lower()) \ |
746 | + .filter(func.lower(Identity.source) == source.lower()).first() |
747 | if not identity: |
748 | identity = Identity(source, user) |
749 | identity.account_id = account_id |
750 | - session.save_or_update(identity) |
751 | - session.flush() |
752 | - session.close() |
753 | + event.session.save_or_update(identity) |
754 | identify_cache.clear() |
755 | |
756 | del self.tokens[token] |
757 | event.addresponse(u'Identity added') |
758 | - log.info(u"Attached identity %s (%s on %s) to account %s by %s/%s (%s) with token %s", identity.id, identity.identity, identity.source, account_id, event.account, event.identity, event.sender['connection'], token) |
759 | + |
760 | + event.session.flush() |
761 | + log.info(u"Attached identity %s (%s on %s) to account %s by %s/%s (%s) with token %s", |
762 | + identity.id, identity.identity, identity.source, account_id, event.account, |
763 | + event.identity, event.sender['connection'], token) |
764 | |
765 | @match(r'^remove\s+identity\s+(.+?)\s+on\s+(\S+)(?:\s+from\s+(\S+))?$') |
766 | def remove(self, event, user, source, username): |
767 | - session = ibid.databases.ibid() |
768 | - |
769 | if not username: |
770 | - account = session.query(Account).get(event.account) |
771 | + account = event.session.query(Account).get(event.account) |
772 | else: |
773 | if not auth_responses(event, 'accounts'): |
774 | return |
775 | - account = session.query(Account).filter_by(username=username).first() |
776 | + account = event.session.query(Account).filter_by(username=username).first() |
777 | if not account: |
778 | event.addresponse(u"I don't know who %s is", username) |
779 | return |
780 | |
781 | - identity = session.query(Identity).filter_by(account_id=account.id).filter(func.lower(Identity.identity)==user.lower()).filter(func.lower(Identity.source)==source.lower()).first() |
782 | + identity = event.session.query(Identity) \ |
783 | + .filter_by(account_id=account.id) \ |
784 | + .filter(func.lower(Identity.identity) == user.lower()) \ |
785 | + .filter(func.lower(Identity.source) == source.lower()).first() |
786 | if not identity: |
787 | event.addresponse(u"I don't know about that identity") |
788 | else: |
789 | identity.account_id = None |
790 | - session.save_or_update(identity) |
791 | - session.flush() |
792 | + event.session.save_or_update(identity) |
793 | identify_cache.clear() |
794 | event.addresponse(True) |
795 | - log.info(u"Removed identity %s (%s on %s) from account %s (%s) by %s/%s (%s)", identity.id, identity.identity, identity.source, account.id, account.username, event.account, event.identity, event.sender['connection']) |
796 | - |
797 | - session.close() |
798 | + log.info(u"Removed identity %s (%s on %s) from account %s (%s) by %s/%s (%s)", |
799 | + identity.id, identity.identity, identity.source, account.id, |
800 | + account.username, event.account, event.identity, event.sender['connection']) |
801 | |
802 | class Attributes(Processor): |
803 | u"""set (my|<account>) <name> to <value>""" |
804 | @@ -191,13 +211,12 @@ |
805 | |
806 | @match(r"^set\s+(my|.+?)(?:\'s)?\s+(.+)\s+to\s+(.+)$") |
807 | def attribute(self, event, username, name, value): |
808 | - session = ibid.databases.ibid() |
809 | |
810 | if username.lower() == 'my': |
811 | if not event.account: |
812 | event.addresponse(u"I don't know who you are") |
813 | return |
814 | - account = session.query(Account).filter_by(id=event.account).first() |
815 | + account = event.session.query(Account).filter_by(id=event.account).first() |
816 | if not account: |
817 | event.addresponse(u"%s doesn't exist. Please use 'add account' first", username) |
818 | return |
819 | @@ -205,17 +224,17 @@ |
820 | else: |
821 | if not auth_responses(event, 'accounts'): |
822 | return |
823 | - account = session.query(Account).filter_by(username=username).first() |
824 | + account = event.session.query(Account).filter_by(username=username).first() |
825 | if not account: |
826 | event.addresponse(u"I don't know who %s is", username) |
827 | return |
828 | |
829 | account.attributes.append(Attribute(name, value)) |
830 | - session.save_or_update(account) |
831 | - session.flush() |
832 | - session.close() |
833 | + event.session.save_or_update(account) |
834 | event.addresponse(True) |
835 | - log.info(u"Added attribute '%s' = '%s' to account %s (%s) by %s/%s (%s)", name, value, account.id, account.username, event.account, event.identity, event.sender['connection']) |
836 | + log.info(u"Added attribute '%s' = '%s' to account %s (%s) by %s/%s (%s)", |
837 | + name, value, account.id, account.username, event.account, |
838 | + event.identity, event.sender['connection']) |
839 | |
840 | class Describe(Processor): |
841 | u"""who (am I|is <username>)""" |
842 | @@ -223,19 +242,18 @@ |
843 | |
844 | @match(r'^who\s+(?:is|am)\s+(I|.+?)$') |
845 | def describe(self, event, username): |
846 | - session = ibid.databases.ibid() |
847 | if username.upper() == 'I': |
848 | if not event.account: |
849 | - identity = session.query(Identity).get(event.identity) |
850 | + identity = event.session.query(Identity).get(event.identity) |
851 | event.addresponse(u"%(name)s on %(source)s", { |
852 | 'name': identity.identity, |
853 | 'source': identity.source, |
854 | }) |
855 | return |
856 | - account = session.query(Account).get(event.account) |
857 | + account = event.session.query(Account).get(event.account) |
858 | |
859 | else: |
860 | - account = session.query(Account).filter_by(username=username).first() |
861 | + account = event.session.query(Account).filter_by(username=username).first() |
862 | if not account: |
863 | event.addresponse(u"I don't know who %s is", username) |
864 | return |
865 | @@ -244,7 +262,6 @@ |
866 | 'accountname': account.username, |
867 | 'identities': u', '.join(u'%s on %s' % (identity.identity, identity.source) for identity in account.identities), |
868 | }) |
869 | - session.close() |
870 | |
871 | class Identify(Processor): |
872 | |
873 | @@ -256,25 +273,26 @@ |
874 | (event.identity, event.account) = identify_cache[(event.source, event.sender['connection'])] |
875 | return |
876 | |
877 | - session = ibid.databases.ibid() |
878 | - identity = session.query(Identity)\ |
879 | - .options(eagerload('account'))\ |
880 | - .filter(func.lower(Identity.source) == event.source.lower())\ |
881 | - .filter(func.lower(Identity.identity) == event.sender['id'].lower())\ |
882 | + identity = event.session.query(Identity) \ |
883 | + .options(eagerload('account')) \ |
884 | + .filter(func.lower(Identity.source) == event.source.lower()) \ |
885 | + .filter(func.lower(Identity.identity) == event.sender['id'].lower()) \ |
886 | .first() |
887 | if not identity: |
888 | identity = Identity(event.source, event.sender['id']) |
889 | - session.save_or_update(identity) |
890 | + event.session.save_or_update(identity) |
891 | try: |
892 | - session.flush() |
893 | + event.session.commit() |
894 | log.info(u'Created identity %s for %s on %s', identity.id, identity.identity, identity.source) |
895 | except IntegrityError: |
896 | - session.expunge(identity) |
897 | + event.session.rollback() |
898 | + event.session.close() |
899 | + del event['session'] |
900 | log.debug(u'Race encountered creating identity for %s on %s', event.sender['id'], event.source) |
901 | - identity = session.query(Identity)\ |
902 | - .options(eagerload('account'))\ |
903 | - .filter(func.lower(Identity.source) == event.source.lower())\ |
904 | - .filter(func.lower(Identity.identity) == event.sender['id'].lower())\ |
905 | + identity = event.session.query(Identity) \ |
906 | + .options(eagerload('account')) \ |
907 | + .filter(func.lower(Identity.source) == event.source.lower()) \ |
908 | + .filter(func.lower(Identity.identity) == event.sender['id'].lower()) \ |
909 | .one() |
910 | |
911 | event.identity = identity.id |
912 | @@ -284,29 +302,9 @@ |
913 | event.account = None |
914 | identify_cache[(event.source, event.sender['connection'])] = (event.identity, event.account) |
915 | |
916 | - session.close() |
917 | - |
918 | -def identify(source, user): |
919 | - |
920 | - session = ibid.databases.ibid() |
921 | - |
922 | - identity = session.query(Identity).filter(func.lower(Identity.source)==source.lower()).filter(func.lower(Identity.identity)==user.lower()).first() |
923 | - account = session.query(Account).filter_by(username=user).first() |
924 | - |
925 | - if not account and not identity: |
926 | - return None |
927 | - if not account: |
928 | - return identity |
929 | - if not identity or identity in account.identities: |
930 | - return account |
931 | - return (account, identity) |
932 | - |
933 | -def get_identities(event, session=None): |
934 | - if not session: |
935 | - session = ibid.databases.ibid() |
936 | - |
937 | +def get_identities(event): |
938 | if event.account: |
939 | - account = session.query(Account).get(event.account) |
940 | + account = event.session.query(Account).get(event.account) |
941 | return [identity.id for identity in account.identities] |
942 | else: |
943 | return (event.identity,) |
944 | |
945 | === modified file 'ibid/plugins/karma.py' |
946 | --- ibid/plugins/karma.py 2009-05-01 12:17:57 +0000 |
947 | +++ ibid/plugins/karma.py 2009-05-03 16:33:10 +0000 |
948 | @@ -4,7 +4,6 @@ |
949 | from sqlalchemy import Column, Integer, Unicode, DateTime, Table |
950 | from sqlalchemy.sql import func |
951 | |
952 | -import ibid |
953 | from ibid.plugins import Processor, match, handler, authorise |
954 | from ibid.config import Option, BoolOption, IntOption |
955 | from ibid.models import Base, VersionedSchema |
956 | @@ -59,8 +58,8 @@ |
957 | if subject.lower() in self.ignore: |
958 | return |
959 | |
960 | - session = ibid.databases.ibid() |
961 | - karma = session.query(Karma).filter(func.lower(Karma.subject)==subject.lower()).first() |
962 | + karma = event.session.query(Karma) \ |
963 | + .filter(func.lower(Karma.subject) == subject.lower()).first() |
964 | if not karma: |
965 | karma = Karma(subject) |
966 | |
967 | @@ -82,14 +81,12 @@ |
968 | if karma.value == 0 and karma.changes <= self.importance: |
969 | change = u'Forgotten (unimportant)' |
970 | |
971 | - session.delete(karma) |
972 | + event.session.delete(karma) |
973 | else: |
974 | - session.save_or_update(karma) |
975 | - |
976 | - session.flush() |
977 | - session.close() |
978 | - |
979 | - log.info(u"%s karma for '%s' by %s/%s (%s) because: %s", change, subject, event.account, event.identity, event.sender['connection'], reason) |
980 | + event.session.save_or_update(karma) |
981 | + |
982 | + log.info(u"%s karma for '%s' by %s/%s (%s) because: %s", |
983 | + change, subject, event.account, event.identity, event.sender['connection'], reason) |
984 | |
985 | if self.reply: |
986 | event.addresponse(True) |
987 | @@ -103,8 +100,8 @@ |
988 | |
989 | @match(r'^karma\s+(?:for\s+)?(.+)$') |
990 | def handle_karma(self, event, subject): |
991 | - session = ibid.databases.ibid() |
992 | - karma = session.query(Karma).filter(func.lower(Karma.subject)==subject.lower()).first() |
993 | + karma = event.session.query(Karma) \ |
994 | + .filter(func.lower(Karma.subject) == subject.lower()).first() |
995 | if not karma: |
996 | event.addresponse(u'nobody cares, dude') |
997 | elif karma.value == 0: |
998 | @@ -114,17 +111,16 @@ |
999 | 'subject': subject, |
1000 | 'value': karma.value, |
1001 | }) |
1002 | - session.close() |
1003 | |
1004 | @match(r'^(reverse\s+)?karmaladder$') |
1005 | def ladder(self, event, reverse): |
1006 | - session = ibid.databases.ibid() |
1007 | - karmas = session.query(Karma).order_by(reverse and Karma.value.asc() or Karma.value.desc()).limit(30).all() |
1008 | + karmas = event.session.query(Karma) \ |
1009 | + .order_by(reverse and Karma.value.asc() or Karma.value.desc()) \ |
1010 | + .limit(30).all() |
1011 | if karmas: |
1012 | event.addresponse(', '.join(['%s: %s (%s)' % (karmas.index(karma), karma.subject, karma.value) for karma in karmas])) |
1013 | else: |
1014 | event.addresponse(u"I don't really care about anything") |
1015 | - session.close() |
1016 | |
1017 | class Forget(Processor): |
1018 | u"""forget karma for <subject> [[reason]]""" |
1019 | @@ -138,17 +134,16 @@ |
1020 | @match(r'^forget\s+karma\s+for\s+(.+?)(?:\s*[[{(]+\s*(.+?)\s*[\]})]+)?$') |
1021 | @authorise |
1022 | def forget(self, event, subject, reason): |
1023 | - session = ibid.databases.ibid() |
1024 | - karma = session.query(Karma).filter(func.lower(Karma.subject)==subject.lower()).first() |
1025 | + karma = event.session.query(Karma) \ |
1026 | + .filter(func.lower(Karma.subject) == subject.lower()).first() |
1027 | if not karma: |
1028 | karma = Karma(subject) |
1029 | event.addresponse(u"I was pretty ambivalent about %s, anyway", subject) |
1030 | |
1031 | - session.delete(karma) |
1032 | - session.flush() |
1033 | - session.close() |
1034 | + event.session.delete(karma) |
1035 | |
1036 | - log.info(u"Forgot karma for '%s' by %s/%s (%s) because: %s", subject, event.account, event.identity, event.sender['connection'], reason) |
1037 | + log.info(u"Forgot karma for '%s' by %s/%s (%s) because: %s", |
1038 | + subject, event.account, event.identity, event.sender['connection'], reason) |
1039 | event.addresponse(True) |
1040 | |
1041 | # vi: set et sta sw=4 ts=4: |
1042 | |
1043 | === modified file 'ibid/plugins/memo.py' |
1044 | --- ibid/plugins/memo.py 2009-05-01 12:27:24 +0000 |
1045 | +++ ibid/plugins/memo.py 2009-05-03 16:33:10 +0000 |
1046 | @@ -5,10 +5,9 @@ |
1047 | from sqlalchemy.orm import relation |
1048 | from sqlalchemy.sql import func |
1049 | |
1050 | -import ibid |
1051 | from ibid.plugins import Processor, handler, match, authorise |
1052 | from ibid.config import Option |
1053 | -from ibid.plugins.auth import permission |
1054 | +from ibid.auth import permission |
1055 | from ibid.plugins.identity import get_identities |
1056 | from ibid.models import Base, VersionedSchema, Identity, Account |
1057 | from ibid.utils import ago |
1058 | @@ -51,10 +50,12 @@ |
1059 | @match(r'^(?:please\s+)?(tell|pm|privmsg|msg)\s+(\S+)\s+(?:(?:that|to)\s+)?(.+)$') |
1060 | @authorise |
1061 | def tell(self, event, how, who, memo): |
1062 | - session = ibid.databases.ibid() |
1063 | - to = session.query(Identity).filter(func.lower(Identity.identity)==who.lower()).filter_by(source=event.source).first() |
1064 | + to = event.session.query(Identity) \ |
1065 | + .filter(func.lower(Identity.identity) == who.lower()) \ |
1066 | + .filter_by(source=event.source).first() |
1067 | if not to: |
1068 | - account = session.query(Account).filter(func.lower(Account.username)==who.lower()).first() |
1069 | + account = event.session.query(Account) \ |
1070 | + .filter(func.lower(Account.username) == who.lower()).first() |
1071 | if account: |
1072 | for identity in account.identities: |
1073 | if identity.source == event.source: |
1074 | @@ -63,27 +64,32 @@ |
1075 | identity = account.identities[0] |
1076 | if not to: |
1077 | to = Identity(event.source, who) |
1078 | - session.save(to) |
1079 | - session.flush() |
1080 | + event.session.save(to) |
1081 | + |
1082 | + event.session.flush() |
1083 | log.info(u"Created identity %s for %s on %s", to.id, to.identity, to.source) |
1084 | |
1085 | - if permission(u'recvmemo', to.account and to.account.id or None, to.source) != 'yes': |
1086 | + if permission(u'recvmemo', to.account and to.account.id or None, to.source, event.session) != 'yes': |
1087 | event.addresponse(u'Just tell %s yourself', who) |
1088 | return |
1089 | |
1090 | memo = Memo(event.identity, to.id, memo, how.lower() in ('pm', 'privmsg', 'msg')) |
1091 | - session.save_or_update(memo) |
1092 | - session.flush() |
1093 | - log.info(u"Stored memo %s for %s (%s) from %s (%s): %s", memo.id, to.id, who, event.identity, event.sender['connection'], memo.memo) |
1094 | + event.session.save_or_update(memo) |
1095 | + |
1096 | + event.session.flush() |
1097 | + log.info(u"Stored memo %s for %s (%s) from %s (%s): %s", |
1098 | + memo.id, to.id, who, event.identity, event.sender['connection'], memo.memo) |
1099 | event.memo = memo.id |
1100 | - session.close() |
1101 | memo_cache.clear() |
1102 | |
1103 | event.addresponse(True) |
1104 | |
1105 | -def get_memos(session, event, delivered=False): |
1106 | - identities = get_identities(event, session) |
1107 | - return session.query(Memo).filter_by(delivered=delivered).filter(Memo.to_id.in_(identities)).order_by(Memo.time.asc()).all() |
1108 | +def get_memos(event, delivered=False): |
1109 | + identities = get_identities(event) |
1110 | + return event.session.query(Memo) \ |
1111 | + .filter_by(delivered=delivered) \ |
1112 | + .filter(Memo.to_id.in_(identities)) \ |
1113 | + .order_by(Memo.time.asc()).all() |
1114 | |
1115 | class Deliver(Processor): |
1116 | feature = 'memo' |
1117 | @@ -96,8 +102,7 @@ |
1118 | if event.identity in memo_cache: |
1119 | return |
1120 | |
1121 | - session = ibid.databases.ibid() |
1122 | - memos = get_memos(session, event) |
1123 | + memos = get_memos(event) |
1124 | |
1125 | for memo in memos: |
1126 | # Don't deliver if the user just sent a memo to themself |
1127 | @@ -122,11 +127,9 @@ |
1128 | }) |
1129 | |
1130 | memo.delivered = True |
1131 | - session.save_or_update(memo) |
1132 | - log.info(u"Delivered memo %s to %s (%s)", memo.id, event.identity, event.sender['connection']) |
1133 | - |
1134 | - session.flush() |
1135 | - session.close() |
1136 | + event.session.save_or_update(memo) |
1137 | + log.info(u"Delivered memo %s to %s (%s)", |
1138 | + memo.id, event.identity, event.sender['connection']) |
1139 | |
1140 | if 'memo' not in event: |
1141 | memo_cache[event.identity] = None |
1142 | @@ -146,16 +149,13 @@ |
1143 | if event.identity in memo_cache: |
1144 | return |
1145 | |
1146 | - session = ibid.databases.ibid() |
1147 | - memos = get_memos(session, event) |
1148 | + memos = get_memos(event) |
1149 | |
1150 | if len(memos) > 0: |
1151 | event.addresponse({'reply': u'You have %s messages' % len(memos), 'target': event.sender['id']}) |
1152 | else: |
1153 | memo_cache[event.identity] = None |
1154 | |
1155 | - session.close() |
1156 | - |
1157 | class Messages(Processor): |
1158 | u"""my messages |
1159 | message <number>""" |
1160 | @@ -165,18 +165,15 @@ |
1161 | |
1162 | @match(r'^my\s+messages$') |
1163 | def messages(self, event): |
1164 | - session = ibid.databases.ibid() |
1165 | - memos = get_memos(session, event, True) |
1166 | + memos = get_memos(event, True) |
1167 | if memos: |
1168 | event.addresponse(u', '.join(['%s: %s (%s)' % (memos.index(memo), memo.sender.identity, memo.time.strftime(self.datetime_format)) for memo in memos])) |
1169 | else: |
1170 | event.addresponse(u"Sorry, nobody loves you") |
1171 | - session.close() |
1172 | |
1173 | @match(r'^message\s+(\d+)$') |
1174 | def message(self, event, number): |
1175 | - session = ibid.databases.ibid() |
1176 | - memos = get_memos(session, event, True) |
1177 | + memos = get_memos(event, True) |
1178 | memo = memos[int(number)] |
1179 | event.addresponse(u"From %(sender)s on %(source)s at %(time)s: %(message)s", { |
1180 | 'sender': memo.sender.identity, |
1181 | @@ -184,7 +181,5 @@ |
1182 | 'time': memo.time.strftime(self.datetime_format), |
1183 | 'message': memo.memo, |
1184 | }) |
1185 | - session.close() |
1186 | - |
1187 | |
1188 | # vi: set et sta sw=4 ts=4: |
1189 | |
1190 | === modified file 'ibid/plugins/seen.py' |
1191 | --- ibid/plugins/seen.py 2009-05-01 12:22:37 +0000 |
1192 | +++ ibid/plugins/seen.py 2009-05-03 16:37:03 +0000 |
1193 | @@ -6,7 +6,6 @@ |
1194 | from sqlalchemy.sql import func |
1195 | from sqlalchemy.exceptions import IntegrityError |
1196 | |
1197 | -import ibid |
1198 | from ibid.plugins import Processor, match |
1199 | from ibid.config import Option |
1200 | from ibid.models import Base, VersionedSchema, Identity, Account |
1201 | @@ -51,8 +50,9 @@ |
1202 | if event.type != 'message' and event.type != 'state': |
1203 | return |
1204 | |
1205 | - session = ibid.databases.ibid() |
1206 | - sighting = session.query(Sighting).filter_by(identity_id=event.identity).filter_by(type=event.type).first() |
1207 | + sighting = event.session.query(Sighting) \ |
1208 | + .filter_by(identity_id=event.identity) \ |
1209 | + .filter_by(type=event.type).first() |
1210 | if not sighting: |
1211 | sighting = Sighting(event.identity, event.type) |
1212 | |
1213 | @@ -65,12 +65,15 @@ |
1214 | sighting.time = datetime.now() |
1215 | sighting.count = sighting.count + 1 |
1216 | |
1217 | + event.session.save_or_update(sighting) |
1218 | try: |
1219 | - session.save_or_update(sighting) |
1220 | - session.flush() |
1221 | + event.session.commit() |
1222 | except IntegrityError: |
1223 | - log.debug('Race on seen update for identity %s', event.identity) |
1224 | - session.close() |
1225 | + event.session.rollback() |
1226 | + event.session.close() |
1227 | + del event['session'] |
1228 | + log.debug(u'Race encountered updating seen for %s on %s', |
1229 | + event.sender['id'], event.source) |
1230 | |
1231 | class Seen(Processor): |
1232 | u"""seen <who>""" |
1233 | @@ -81,14 +84,15 @@ |
1234 | @match(r'^(?:have\s+you\s+)?seen\s+(\S+)(?:\s+on\s+(\S+))?$') |
1235 | def handler(self, event, who, source): |
1236 | |
1237 | - session = ibid.databases.ibid() |
1238 | account = None |
1239 | - identity = session.query(Identity).filter(func.lower(Identity.source)==(source and source or event.source).lower()).filter(func.lower(Identity.identity)==who.lower()).first() |
1240 | + identity = event.session.query(Identity) \ |
1241 | + .filter(func.lower(Identity.source) == (source and source or event.source).lower()) \ |
1242 | + .filter(func.lower(Identity.identity) == who.lower()).first() |
1243 | if identity and identity.account and not source: |
1244 | account = identity.account |
1245 | |
1246 | if not identity and not source: |
1247 | - account = session.query(Account).filter_by(username=who).first() |
1248 | + account = event.session.query(Account).filter_by(username=who).first() |
1249 | |
1250 | if not identity and not account: |
1251 | event.addresponse(u"I don't know who %s is", who) |
1252 | @@ -98,13 +102,15 @@ |
1253 | states = [] |
1254 | if account: |
1255 | for identity in account.identities: |
1256 | - for sighting in session.query(Sighting).filter_by(identity_id=identity.id).all(): |
1257 | + for sighting in event.session.query(Sighting) \ |
1258 | + .filter_by(identity_id=identity.id).all(): |
1259 | if sighting.type == 'message': |
1260 | messages.append(sighting) |
1261 | else: |
1262 | states.append(sighting) |
1263 | else: |
1264 | - for sighting in session.query(Sighting).filter_by(identity_id=identity.id).all(): |
1265 | + for sighting in event.session.query(Sighting) \ |
1266 | + .filter_by(identity_id=identity.id).all(): |
1267 | if sighting.type == 'message': |
1268 | messages.append(sighting) |
1269 | else: |
1270 | @@ -133,6 +139,5 @@ |
1271 | reply += u" has been %s on %s since %s" % (sighting.value, sighting.identity.source, sighting.time.strftime(self.datetime_format)) |
1272 | |
1273 | event.addresponse(reply) |
1274 | - session.close() |
1275 | |
1276 | # vi: set et sta sw=4 ts=4: |
1277 | |
1278 | === modified file 'ibid/plugins/url.py' |
1279 | --- ibid/plugins/url.py 2009-05-01 12:22:37 +0000 |
1280 | +++ ibid/plugins/url.py 2009-05-02 19:29:44 +0000 |
1281 | @@ -114,11 +114,8 @@ |
1282 | else: |
1283 | url = 'http://%s' % url |
1284 | |
1285 | - session = ibid.databases.ibid() |
1286 | u = URL(url, event.channel, event.identity) |
1287 | - session.save_or_update(u) |
1288 | - session.flush() |
1289 | - session.close() |
1290 | + event.session.save_or_update(u) |
1291 | |
1292 | if self.username != None: |
1293 | self.delicious.add_post(self.username, self.password, event, url) |
1294 | |
1295 | === modified file 'ibid/source/irc.py' |
1296 | --- ibid/source/irc.py 2009-05-01 12:59:07 +0000 |
1297 | +++ ibid/source/irc.py 2009-05-02 19:29:44 +0000 |
1298 | @@ -237,8 +237,9 @@ |
1299 | return u'irc://%s@%s:%s' % (self.nick, self.server, self.port) |
1300 | |
1301 | def auth_hostmask(self, event, credential = None): |
1302 | - session = ibid.databases.ibid() |
1303 | - for credential in session.query(Credential).filter_by(method=u'hostmask').filter_by(account_id=event.account).filter(or_(Credential.source == event.source, Credential.source == None)).all(): |
1304 | + for credential in event.session.query(Credential) \ |
1305 | + .filter_by(method=u'hostmask').filter_by(account_id=event.account) \ |
1306 | + .filter(or_(Credential.source == event.source, Credential.source == None)).all(): |
1307 | if fnmatch(event.sender['connection'], credential.credential): |
1308 | return True |
1309 | |
1310 | |
1311 | === modified file 'scripts/ibid-factpack' |
1312 | --- scripts/ibid-factpack 2009-04-26 11:04:32 +0000 |
1313 | +++ scripts/ibid-factpack 2009-05-02 19:29:44 +0000 |
1314 | @@ -28,7 +28,6 @@ |
1315 | ibid.reload_reloader() |
1316 | ibid.reloader.reload_databases() |
1317 | session = ibid.databases.ibid() |
1318 | -session.begin() |
1319 | |
1320 | if options.remove: |
1321 | factpack = session.query(Factpack).filter_by(name=filename).first() |
1322 | @@ -76,7 +75,6 @@ |
1323 | |
1324 | factpack = Factpack(name) |
1325 | session.save(factpack) |
1326 | -session.flush() |
1327 | |
1328 | existing = [] |
1329 | for names, values in facts: |
1330 | |
1331 | === modified file 'scripts/ibid-plugin' |
1332 | --- scripts/ibid-plugin 2009-05-02 16:20:45 +0000 |
1333 | +++ scripts/ibid-plugin 2009-05-03 16:37:03 +0000 |
1334 | @@ -14,6 +14,7 @@ |
1335 | pass |
1336 | |
1337 | from twisted.python.modules import getModule |
1338 | +from sqlalchemy.exceptions import IntegrityError |
1339 | |
1340 | import ibid |
1341 | import ibid.plugins |
1342 | @@ -80,15 +81,19 @@ |
1343 | username = unicode(getenv('USER')) |
1344 | if not username: |
1345 | username = u'tester' |
1346 | + |
1347 | session = ibid.databases.ibid() |
1348 | + |
1349 | identity = session.query(Identity).filter_by(identity=username).first() |
1350 | if not identity: |
1351 | identity = Identity(u'test_source',username) |
1352 | session.save(identity) |
1353 | - session.flush() |
1354 | + session.commit() |
1355 | identity = session.query(Identity).filter_by(identity=username).first() |
1356 | identity_id = identity.id |
1357 | |
1358 | +session.close() |
1359 | + |
1360 | try: |
1361 | encoding = getenv("LANG").split(".")[1] |
1362 | except: |
1363 | @@ -115,14 +120,28 @@ |
1364 | try: |
1365 | processor.process(event) |
1366 | except Exception: |
1367 | - log.exception(u"Exception occured in %s processor of %s plugin", processor.__class__.__name__, processor.name) |
1368 | + log.exception(u"Exception occured in %s processor of %s plugin", |
1369 | + processor.__class__.__name__, processor.name) |
1370 | event.complain = 'exception' |
1371 | |
1372 | + if 'session' in event: |
1373 | + try: |
1374 | + event.session.commit() |
1375 | + except IntegrityError: |
1376 | + self.log.exception(u"Exception occured committing session from the %s processor of %s plugin", |
1377 | + processor.__class__.__name__, processor.name) |
1378 | + event.complain = u'exception' |
1379 | + event.session.rollback() |
1380 | + event.session.close() |
1381 | + del event['session'] |
1382 | + |
1383 | for response in event.responses: |
1384 | if isinstance(response, dict): |
1385 | response = response['reply'] |
1386 | print 'Response: %s' % response |
1387 | |
1388 | + event.session.close() |
1389 | + |
1390 | if readline: |
1391 | readline.write_history_file('.history') |
1392 | print "\nExiting" |
1393 | |
1394 | === modified file 'scripts/ibid-setup' |
1395 | --- scripts/ibid-setup 2009-05-01 10:39:58 +0000 |
1396 | +++ scripts/ibid-setup 2009-05-02 19:29:44 +0000 |
1397 | @@ -83,7 +83,6 @@ |
1398 | exit(1) |
1399 | |
1400 | session = Session() |
1401 | -session.begin() |
1402 | account = Account(identity) |
1403 | identity = Identity(source, identity) |
1404 | account.identities.append(identity) |
1405 | |
1406 | === modified file 'scripts/ibid_import' |
1407 | --- scripts/ibid_import 2009-02-22 07:43:34 +0000 |
1408 | +++ scripts/ibid_import 2009-05-02 19:29:44 +0000 |
1409 | @@ -63,7 +63,9 @@ |
1410 | return None |
1411 | user = decode(user) |
1412 | |
1413 | - identity = session.query(Identity).filter(func.lower(Identity.identity)==user.lower()).filter(func.lower(Identity.source)==source.lower()).first() |
1414 | + identity = session.query(Identity) \ |
1415 | + .filter(func.lower(Identity.identity) == user.lower()) \ |
1416 | + .filter(func.lower(Identity.source) == source.lower()).first() |
1417 | if not identity: |
1418 | identity = Identity(source, user) |
1419 | identity.created = created |
1420 | @@ -231,5 +233,6 @@ |
1421 | print 'Done' |
1422 | |
1423 | knab.close() |
1424 | + ibid.close() |
1425 | |
1426 | # vi: set et sta sw=4 ts=4: |
Happy reviewing, folks :P
This is one mother of a branch.
We still have the option of attaching identities and accounts to the event. However, I'm not doing that now.