Merge lp:~stefanor/ibid/sqlalchemy-370772 into lp:~ibid-core/ibid/old-trunk-pack-0.92

Proposed by Stefano Rivera
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
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.

To post a comment you must log in.
Revision history for this message
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal

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.

Revision history for this message
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...

Revision history for this message
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal

No reviews yet, so re-submitted to get new diff

Revision history for this message
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.

Revision history for this message
Michael Gorven (mgorven) wrote : Posted in a previous version of this proposal

+ self.log.exception(u"Exception occured in %s processor
of %s plugin", processor.__class__.__name__, processor.name)

Can you just change the log message so something like "Exception occured while
committing session after %s processor of %s plugin".

+ self[name] = scoped_session(sessionmaker(bind=engine))

Do all versions of SQLAlchemy default to using transactions and autoflush?

- session.flush()
         log.info(u"%s %s permission for account %s (%s) by account %s",
actions[action.lower()], name, account.id, account.username, event.account)

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

review: Needs Fixing
Revision history for this message
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)

Revision history for this message
Jonathan Hitchcock (vhata) :
review: Approve
lp:~stefanor/ibid/sqlalchemy-370772 updated
633. By Stefano Rivera

Merge from trunk

Revision history for this message
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.

lp:~stefanor/ibid/sqlalchemy-370772 updated
634. By Stefano Rivera

Commit in plugins, to ensure that Ibid only confirms successful actions (rollback in dispatcher)

Revision history for this message
Stefano Rivera (stefanor) wrote :

r634

Revision history for this message
Michael Gorven (mgorven) wrote :

Why is the session deleted if an exception occurs? Is rolling back not
sufficient?

Revision history for this message
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.

Revision history for this message
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

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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:

Subscribers

People subscribed via source and target branches