Merge lp:~stefanor/ibid/sqlalchemy-0.6-trunk into lp:ibid

Proposed by Stefano Rivera on 2011-06-27
Status: Merged
Approved by: Stefano Rivera on 2012-07-31
Approved revision: 1038
Merged at revision: 1052
Proposed branch: lp:~stefanor/ibid/sqlalchemy-0.6-trunk
Merge into: lp:ibid
Diff against target: 847 lines (+187/-158)
20 files modified
docs/install.rst (+1/-1)
ibid/core.py (+42/-34)
ibid/db/__init__.py (+2/-5)
ibid/db/types.py (+62/-50)
ibid/db/versioned_schema.py (+20/-24)
ibid/plugins/codecontest.py (+1/-1)
ibid/plugins/factoid.py (+6/-6)
ibid/plugins/feeds.py (+1/-1)
ibid/plugins/fun.py (+3/-3)
ibid/plugins/identity.py (+13/-13)
ibid/plugins/karma.py (+12/-5)
ibid/plugins/memo.py (+3/-3)
ibid/plugins/seen.py (+1/-1)
ibid/plugins/urlgrab.py (+1/-1)
ibid/test/__init__.py (+10/-1)
scripts/ibid-factpack (+2/-2)
scripts/ibid-knab-import (+3/-3)
scripts/ibid-plugin (+1/-1)
scripts/ibid-setup (+2/-2)
setup.py (+1/-1)
To merge this branch: bzr merge lp:~stefanor/ibid/sqlalchemy-0.6-trunk
Reviewer Review Type Date Requested Status
Keegan Carruthers-Smith 2011-06-27 Approve on 2012-07-31
Stefano Rivera Approve on 2012-07-31
Jonathan Hitchcock 2011-06-27 Approve on 2011-11-10
Max Rabkin 2011-06-27 Approve on 2011-11-09
Review via email: mp+66033@code.launchpad.net

This proposal supersedes a proposal from 2010-06-16.

Commit message

The massive SQLALchemy 0.6 + 0.7 patch. Only 18 months late :)
Main points:
* Use SQLALchemy 0.6 APIs, dropping 0.5 support.
* Create fullblown SQLAlchemy types for IbidUnicode(Text) rather than use TypeDecorator.

Description of the change

We should be talking about merging this

To post a comment you must log in.
Max Rabkin (max-rabkin) wrote : Posted in a previous version of this proposal

bucket now uses the database

review: Needs Fixing
Keegan Carruthers-Smith (keegan-csmith) wrote : Posted in a previous version of this proposal

Don't know much about sqlalchemy, so gonna abstain.

review: Abstain
Stefano Rivera (stefanor) wrote :

I see from uncommitted diffs on my laptop, that I started trying to get to the bottom of the test failures with SQLAlchemy > 0.5, but I think that's non-trivial.

How about we land this now, and fix it up in trunk?

Approving this because ibid has been running this branch for a while, and there have not been any problems. I did do a quick look over the diff and couldn't see any problems.

review: Approve

by ibid, i mean tibid.

Voting does not meet specified criteria. Required: Approve >= 1, Disapprove == 0. Got: 2 Pending.

Max Rabkin (max-rabkin) wrote :

per Keegan

review: Approve
Download full text (3.4 KiB)

The attempt to merge lp:~stefanor/ibid/sqlalchemy-0.6-trunk into lp:ibid failed. Below is the output from the failed tests.

                                                                        [ERROR]

===============================================================================
[ERROR]: ibid

Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/twisted/trial/runner.py", line 651, in loadByNames
    things.append(self.findByName(name))
  File "/usr/lib/python2.6/dist-packages/twisted/trial/runner.py", line 460, in findByName
    return filenameToModule(name)
  File "/usr/lib/python2.6/dist-packages/twisted/trial/runner.py", line 95, in filenameToModule
    ret = reflect.namedAny(reflect.filenameToModuleName(fn))
  File "/usr/lib/python2.6/dist-packages/twisted/python/reflect.py", line 464, in namedAny
    topLevelPackage = _importAndCheckStack(trialname)
  File "/home/stefanor/ibid/tarmac-trunk/ibid/__init__.py", line 16, in <module>
    import ibid.core
  File "/home/stefanor/ibid/tarmac-trunk/ibid/core.py", line 21, in <module>
    from ibid.db import SchemaVersionException, schema_version_check
  File "/home/stefanor/ibid/tarmac-trunk/ibid/db/__init__.py", line 5, in <module>
    from ibid.db.types import Integer, DateTime, Boolean, \
  File "/home/stefanor/ibid/tarmac-trunk/ibid/db/types.py", line 75, in <module>
    monkey_patch()
  File "/home/stefanor/ibid/tarmac-trunk/ibid/db/types.py", line 9, in monkey_patch
    import sqlalchemy.dialects.postgresql
exceptions.ImportError: No module named dialects.postgresql
-------------------------------------------------------------------------------

FAILED (errors=1)

Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/twisted/python/usage.py", line 241, in parseOptions
    self.postOptions()
  File "/usr/lib/python2.6/dist-packages/twisted/scripts/trial.py", line 295, in postOptions
    self['reporter'] = self._loadReporterByName(self['reporter'])
  File "/usr/lib/python2.6/dist-packages/twisted/scripts/trial.py", line 281, in _loadReporterByName
    for p in plugin.getPlugins(itrial.IReporter):
  File "/usr/lib/python2.6/dist-packages/twisted/plugin.py", line 200, in getPlugins
    allDropins = getCache(package)
--- <exception caught here> ---
  File "/usr/lib/python2.6/dist-packages/twisted/plugin.py", line 165, in getCache
    provider = pluginModule.load()
  File "/usr/lib/python2.6/dist-packages/twisted/python/modules.py", line 381, in load
    return self.pathEntry.pythonPath.moduleLoader(self.name)
  File "/usr/lib/python2.6/dist-packages/twisted/python/reflect.py", line 464, in namedAny
    topLevelPackage = _importAndCheckStack(trialname)
  File "/home/stefanor/ibid/tarmac-trunk/twisted/plugins/ibid_plugin.py", line 10, in <module>
    import ibid
  File "/home/stefanor/ibid/tarmac-trunk/ibid/__init__.py", line 16, in <module>
    import ibid.core
  File "/home/stefanor/ibid/tarmac-trunk/ibid/core.py", line 21, in <module>
    from ibid.db import SchemaVersionException, schema_version_check
  File "/home/stefanor/ibid/tarmac-trunk/ibid/db/__init__.py", line 5, in <module>
    from ibid.db.types import Integer, DateTime, Boolean, \
 ...

Read more...

Jonathan Hitchcock (vhata) wrote :

Surewhynot.

review: Approve

Attempt to merge into lp:ibid failed due to conflicts:

text conflict in ibid/test/__init__.py

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Stefano Rivera (stefanor) wrote :

Here's a biscuit, tarmac

review: Approve

blind approvals ftw

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'docs/install.rst'
2--- docs/install.rst 2010-09-26 22:55:15 +0000
3+++ docs/install.rst 2012-07-31 10:05:22 +0000
4@@ -50,7 +50,7 @@
5 * `Twisted framework <http://twistedmatrix.com/>`_ (core sources)
6 * Twisted Words (IRC, XMPP)
7 * `Wokkel <http://wokkel.ik.nu/>`_. (XMPP)
8-* `SQLAlchemy <http://www.sqlalchemy.org/>`_ 0.5 preferred, 0.4 compatible.
9+* `SQLAlchemy <http://www.sqlalchemy.org/>`_ 0.6 or later.
10 * `ConfigObj <http://www.voidspace.org.uk/python/configobj.html>`_ >= 4.7.0
11 * `python-dateutil <http://labix.org/python-dateutil>`_
12 * `SOAPpy <http://pywebsvcs.sourceforge.net/>`_ [#soappy-install]_
13
14=== modified file 'ibid/core.py'
15--- ibid/core.py 2012-07-08 00:38:43 +0000
16+++ ibid/core.py 2012-07-31 10:05:22 +0000
17@@ -14,7 +14,7 @@
18 from twisted.python.modules import getModule
19 from sqlalchemy import create_engine
20 from sqlalchemy.orm import sessionmaker, scoped_session
21-from sqlalchemy.exceptions import IntegrityError
22+from sqlalchemy.exc import IntegrityError
23
24 import ibid
25 from ibid.event import Event
26@@ -348,39 +348,47 @@
27 assert_unicode=True, echo=echo
28 )
29
30- else:
31- if uri.startswith(u'mysql://'):
32- if u'?' not in uri:
33- uri += u'?charset=utf8'
34- else:
35- params = parse_qs(uri.split(u'?', 1)[1])
36- if u'charset' not in params:
37- uri += u'&charset=utf8'
38-
39- engine = create_engine(uri, encoding='utf-8',
40- convert_unicode=True, assert_unicode=True, echo=echo)
41-
42- if uri.startswith('mysql://'):
43- class MySQLModeListener(object):
44- def connect(self, dbapi_con, con_record):
45- dbapi_con.set_sql_mode("ANSI")
46- mysql_engine = ibid.config.get('mysql_engine', 'InnoDB')
47- c = dbapi_con.cursor()
48- c.execute("SET storage_engine=%s;" % mysql_engine)
49- c.execute("SET time_zone='+0:00';")
50- c.close()
51- engine.pool.add_listener(MySQLModeListener())
52-
53- engine.dialect.use_ansiquotes = True
54-
55- elif uri.startswith('postgres://'):
56- class PGSQLModeListener(object):
57- def connect(self, dbapi_con, con_record):
58- c = dbapi_con.cursor()
59- c.execute("SET TIME ZONE UTC")
60- c.close()
61-
62- engine.pool.add_listener(PGSQLModeListener())
63+ elif uri.startswith(u'mysql://'):
64+ if u'?' not in uri:
65+ uri += u'?'
66+ params = parse_qs(uri.split(u'?', 1)[1])
67+ if u'charset' not in params:
68+ uri += u'&charset=utf8'
69+ if u'sql_mode' not in params:
70+ uri += u'&sql_mode=ANSI_QUOTES'
71+ # As recommended by SQLAlchemy due to a memory leak:
72+ # http://www.sqlalchemy.org/trac/wiki/DatabaseNotes
73+ if u'use_unicode' not in params:
74+ uri += u'&use_unicode=0'
75+
76+ engine = create_engine(uri, encoding='utf-8',
77+ convert_unicode=True, assert_unicode=True, echo=echo,
78+ # MySQL closes 8hr old connections:
79+ pool_recycle=3600)
80+
81+ class MySQLModeListener(object):
82+ def connect(self, dbapi_con, con_record):
83+ mysql_engine = ibid.config.get('mysql_engine', 'InnoDB')
84+ c = dbapi_con.cursor()
85+ c.execute("SET SESSION storage_engine=%s;"
86+ % mysql_engine)
87+ c.execute("SET SESSION time_zone='+0:00';")
88+ c.close()
89+ engine.pool.add_listener(MySQLModeListener())
90+
91+ elif uri.startswith('postgres://'):
92+ engine = create_engine(uri, encoding='utf-8',
93+ convert_unicode=True, assert_unicode=True, echo=echo,
94+ # Ensure decoded unicode values are returned:
95+ use_native_unicode=False)
96+
97+ class PGSQLModeListener(object):
98+ def connect(self, dbapi_con, con_record):
99+ c = dbapi_con.cursor()
100+ c.execute("SET TIME ZONE UTC")
101+ c.close()
102+
103+ engine.pool.add_listener(PGSQLModeListener())
104
105 self[name] = scoped_session(sessionmaker(bind=engine))
106
107
108=== modified file 'ibid/db/__init__.py'
109--- ibid/db/__init__.py 2011-01-24 11:38:54 +0000
110+++ ibid/db/__init__.py 2012-07-31 10:05:22 +0000
111@@ -2,7 +2,7 @@
112 # Released under terms of the MIT/X/Expat Licence. See COPYING for details.
113 import warnings as _warnings
114
115-from ibid.db.types import TypeDecorator, Integer, DateTime, Boolean, \
116+from ibid.db.types import Integer, DateTime, Boolean, \
117 IbidUnicode, IbidUnicodeText
118
119 from sqlalchemy import Table, Column, ForeignKey, Index, UniqueConstraint, \
120@@ -11,7 +11,7 @@
121 from sqlalchemy.sql import func
122 from sqlalchemy.ext.declarative import declarative_base as _declarative_base
123
124-from sqlalchemy.exceptions import IntegrityError, SADeprecationWarning
125+from sqlalchemy.exc import IntegrityError, SADeprecationWarning
126
127 metadata = _MetaData()
128 Base = _declarative_base(metadata=metadata)
129@@ -19,9 +19,6 @@
130 from ibid.db.versioned_schema import VersionedSchema, SchemaVersionException, \
131 schema_version_check, upgrade_schemas
132
133-# We use SQLAlchemy 0.4 compatible .save_or_update() functions
134-_warnings.filterwarnings('ignore', 'Use session.add\(\)', SADeprecationWarning)
135-
136 def get_regexp_op(session):
137 "Return a regexp operator"
138 if session.bind.engine.name in ('postgres', 'postgresql'):
139
140=== modified file 'ibid/db/types.py'
141--- ibid/db/types.py 2010-01-17 20:28:33 +0000
142+++ ibid/db/types.py 2012-07-31 10:05:22 +0000
143@@ -1,65 +1,77 @@
144-# Copyright (c) 2009-2010, Stefano Rivera
145+# Copyright (c) 2009-2011, Stefano Rivera
146 # Released under terms of the MIT/X/Expat Licence. See COPYING for details.
147
148-from sqlalchemy.types import TypeDecorator, Integer, DateTime, Boolean, \
149+from sqlalchemy.types import Integer, DateTime, Boolean, \
150 Unicode as _Unicode, UnicodeText as _UnicodeText
151
152-class _CIDecorator(TypeDecorator):
153- "Abstract class for collation aware columns"
154-
155- def __init__(self, length=None, case_insensitive=False):
156- self.case_insensitive = case_insensitive
157- super(_CIDecorator, self).__init__(length=length)
158-
159- def load_dialect_impl(self, dialect):
160- if hasattr(dialect, 'name'):
161- self.dialect = dialect.name
162- # SQLAlchemy 0.4:
163- else:
164- self.dialect = {
165- 'SQLiteDialect': 'sqlite',
166- 'PGDialect': 'postgres',
167- 'MySQLDialect': 'mysql',
168- }[dialect.__class__.__name__]
169-
170- return dialect.type_descriptor(self.impl)
171-
172- def get_col_spec(self):
173- colspec = self.impl.get_col_spec()
174- if hasattr(self, 'case_insensitive'):
175- collation = None
176- if self.dialect == 'mysql':
177- if self.case_insensitive:
178- collation = 'utf8_general_ci'
179- else:
180- collation = 'utf8_bin'
181- elif self.dialect == 'sqlite':
182- if self.case_insensitive:
183- collation = 'NOCASE'
184- else:
185- collation = 'BINARY'
186- elif self.dialect == 'postgres' and self.case_insensitive:
187- return 'CITEXT'
188-
189- if collation is not None:
190- return colspec + ' COLLATE ' + collation
191- return colspec
192-
193-class IbidUnicode(_CIDecorator):
194+
195+def monkey_patch():
196+ import sqlalchemy.dialects.postgresql
197+ sqlalchemy.dialects.postgresql.dialect.ischema_names['citext'] = IbidUnicodeText
198+ def postgres_visit_IBID_VARCHAR(self, type_):
199+ if type_.case_insensitive:
200+ return 'CITEXT'
201+ else:
202+ return self.visit_VARCHAR(type_)
203+ sqlalchemy.dialects.postgresql.dialect.type_compiler.visit_IBID_VARCHAR = postgres_visit_IBID_VARCHAR
204+ def postgres_visit_IBID_TEXT(self, type_):
205+ if type_.case_insensitive:
206+ return 'CITEXT'
207+ else:
208+ return self.visit_TEXT(type_)
209+ sqlalchemy.dialects.postgresql.dialect.type_compiler.visit_IBID_TEXT = postgres_visit_IBID_TEXT
210+
211+ import sqlalchemy.dialects.sqlite
212+ def sqlite_visit_IBID_VARCHAR(self, type_):
213+ if type_.case_insensitive:
214+ collation = 'NOCASE'
215+ else:
216+ collation = 'BINARY'
217+ return self.visit_VARCHAR(type_) + ' COLLATE ' + collation
218+ sqlalchemy.dialects.sqlite.dialect.type_compiler.visit_IBID_VARCHAR = sqlite_visit_IBID_VARCHAR
219+ def sqlite_visit_IBID_TEXT(self, type_):
220+ if type_.case_insensitive:
221+ collation = 'NOCASE'
222+ else:
223+ collation = 'BINARY'
224+ return self.visit_TEXT(type_) + ' COLLATE ' + collation
225+ sqlalchemy.dialects.sqlite.dialect.type_compiler.visit_IBID_TEXT = sqlite_visit_IBID_TEXT
226+
227+ import sqlalchemy.dialects.mysql
228+ def mysql_visit_IBID_VARCHAR(self, type_):
229+ if type_.case_insensitive:
230+ collation = 'utf8_general_ci'
231+ else:
232+ collation = 'utf8_bin'
233+ return self.visit_VARCHAR(type_) + ' COLLATE ' + collation
234+ sqlalchemy.dialects.mysql.dialect.type_compiler.visit_IBID_VARCHAR = sqlite_visit_IBID_VARCHAR
235+ def mysql_visit_IBID_TEXT(self, type_):
236+ if type_.case_insensitive:
237+ collation = 'utf8_general_ci'
238+ else:
239+ collation = 'utf8_bin'
240+ return self.visit_TEXT(type_) + ' COLLATE ' + collation
241+ sqlalchemy.dialects.mysql.dialect.type_compiler.visit_IBID_TEXT = sqlite_visit_IBID_TEXT
242+
243+class IbidUnicode(_Unicode):
244 "Collaiton aware Unicode"
245
246- impl = _Unicode
247+ __visit_name__ = 'IBID_VARCHAR'
248
249- def __init__(self, length, **kwargs):
250+ def __init__(self, length, case_insensitive=False, **kwargs):
251+ self.case_insensitive = case_insensitive
252 super(IbidUnicode, self).__init__(length, **kwargs)
253
254-class IbidUnicodeText(_CIDecorator):
255+class IbidUnicodeText(_UnicodeText):
256 "Collation aware UnicodeText"
257
258- impl = _UnicodeText
259+ __visit_name__ = 'IBID_TEXT'
260
261- def __init__(self, index_length=8, **kwargs):
262+ def __init__(self, index_length=8, case_insensitive=False, **kwargs):
263+ self.case_insensitive = case_insensitive
264 self.index_length = index_length
265- super(IbidUnicodeText, self).__init__(length=None, **kwargs)
266+ super(IbidUnicodeText, self).__init__(**kwargs)
267+
268+monkey_patch()
269
270 # vi: set et sta sw=4 ts=4:
271
272=== modified file 'ibid/db/versioned_schema.py'
273--- ibid/db/versioned_schema.py 2010-06-22 00:04:13 +0000
274+++ ibid/db/versioned_schema.py 2012-07-31 10:05:22 +0000
275@@ -4,14 +4,11 @@
276 import logging
277 import re
278
279-from sqlalchemy import Column, Index, UniqueConstraint, MetaData, \
280- __version__ as _sqlalchemy_version
281-from sqlalchemy.exceptions import InvalidRequestError, OperationalError, \
282+from sqlalchemy import Column, Index, CheckConstraint, UniqueConstraint, \
283+ MetaData, __version__ as _sqlalchemy_version
284+from sqlalchemy.exc import InvalidRequestError, OperationalError, \
285 ProgrammingError, InternalError
286-if _sqlalchemy_version < '0.5':
287- NoResultFound = InvalidRequestError
288-else:
289- from sqlalchemy.orm.exc import NoResultFound
290+from sqlalchemy.orm.exc import NoResultFound
291
292 from ibid.db.types import Integer, IbidUnicodeText, IbidUnicode
293
294@@ -19,6 +16,11 @@
295
296 log = logging.getLogger('ibid.db.versioned_schema')
297
298+if _sqlalchemy_version < '0.6':
299+ pg_engine = 'postgres'
300+else:
301+ pg_engine = 'postgresql'
302+
303 class VersionedSchema(object):
304 """For an initial table schema, set
305 table.versioned_schema = VersionedSchema(__table__, 1)
306@@ -77,7 +79,7 @@
307 self._create_table()
308
309 schema = Schema(unicode(self.table.name), self.version)
310- session.save_or_update(schema)
311+ session.add(schema)
312 return
313 Schema.__table__ = self._get_reflected_model()
314
315@@ -91,7 +93,7 @@
316 self._create_table()
317
318 schema = Schema(unicode(self.table.name), self.version)
319- session.save_or_update(schema)
320+ session.add(schema)
321
322 elif self.version > schema.version:
323 for version in range(schema.version + 1, self.version + 1):
324@@ -103,7 +105,7 @@
325 getattr(self, 'upgrade_%i_to_%i' % (version - 1, version))()
326
327 schema.version = version
328- session.save_or_update(schema)
329+ session.add(schema)
330
331 self.upgrade_reflected_model = \
332 MetaData(session.bind, reflect=True)
333@@ -126,7 +128,7 @@
334
335 if session.bind.engine.name == 'sqlite':
336 return 'ix_%s_%s' % (self.table.name, col.name)
337- elif session.bind.engine.name == 'postgres':
338+ elif session.bind.engine.name == pg_engine:
339 return '%s_%s_key' % (self.table.name, col.name)
340 elif session.bind.engine.name == 'mysql':
341 return col.name
342@@ -175,6 +177,8 @@
343 ('constraints', old_constraints),
344 ('indexes', old_indexes)):
345 for constraint in old_list:
346+ if isinstance(constraint, CheckConstraint):
347+ continue
348 if any(True for column in constraint.columns
349 if isinstance(column.type, IbidUnicodeText)):
350 indices.append((
351@@ -248,7 +252,7 @@
352 query = 'ALTER TABLE "%s" ADD %s INDEX "%s" ("%s"(%i));' % (
353 self.table.name, col.unique and 'UNIQUE' or '',
354 self._index_name(col), col.name, col.type.index_length)
355- elif engine == 'postgres':
356+ elif engine == pg_engine:
357 # SQLAlchemy hangs if it tries to do this, because it forgets the ;
358 query = 'CREATE %s INDEX "%s" ON "%s" ("%s")' % (
359 col.unique and 'UNIQUE' or '',self._index_name(col),
360@@ -271,7 +275,7 @@
361 return
362 raise
363 except ProgrammingError, e:
364- if engine == 'postgres' and u'already exists' in unicode(e):
365+ if engine == pg_engine and u'already exists' in unicode(e):
366 return
367 raise
368
369@@ -296,21 +300,13 @@
370 raise
371
372 except ProgrammingError, e:
373- if engine == 'postgres' and u'does not exist' in unicode(e):
374- return
375- # In SQLAlchemy 0.4, the InternalError below is a ProgrammingError
376- # and can't be executed in the upgrade transaction:
377- if engine == 'postgres' and u'requires' in unicode(e):
378- self.upgrade_session.bind.execute(
379- 'ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (
380- self.table.name, self._index_name(col)))
381- return
382- raise
383+ if engine == pg_engine and u'does not exist' in unicode(e):
384+ return
385
386 # Postgres constraints can be attached to tables and can't be dropped
387 # at DB level.
388 except InternalError, e:
389- if engine == 'postgres':
390+ if engine == pg_engine:
391 self.upgrade_session.execute(
392 'ALTER TABLE "%s" DROP CONSTRAINT "%s"' % (
393 self.table.name, self._index_name(col)))
394
395=== modified file 'ibid/plugins/codecontest.py'
396--- ibid/plugins/codecontest.py 2011-10-30 17:19:07 +0000
397+++ ibid/plugins/codecontest.py 2012-07-31 10:05:22 +0000
398@@ -239,7 +239,7 @@
399 usaco_account[0].value = usaco_user
400 else:
401 account.attributes.append(Attribute('usaco_account', usaco_user))
402- event.session.save_or_update(account)
403+ event.session.add(account)
404 event.session.commit()
405
406 event.addresponse(u'Done')
407
408=== modified file 'ibid/plugins/factoid.py'
409--- ibid/plugins/factoid.py 2011-08-12 10:04:25 +0000
410+++ ibid/plugins/factoid.py 2012-07-31 10:05:22 +0000
411@@ -82,7 +82,7 @@
412 .filter(FactoidName.name.like('%#_#%%', escape='#')) \
413 .all():
414 row.wild = True
415- self.upgrade_session.save_or_update(row)
416+ self.upgrade_session.add(row)
417 def upgrade_7_to_8(self):
418 self.drop_index(self.table.c._name)
419 self.alter_column(Column('name',
420@@ -401,7 +401,7 @@
421
422 name = FactoidName(unicode(target), event.identity)
423 factoid.names.append(name)
424- event.session.save_or_update(factoid)
425+ event.session.add(factoid)
426 event.session.commit()
427 event.addresponse(True)
428 log.info(u"Added name '%s' to factoid %s (%s) by %s/%s (%s)",
429@@ -607,7 +607,7 @@
430 factoid = Factoid()
431 fname = FactoidName(unicode(name), event.identity)
432 factoid.names.append(fname)
433- event.session.save_or_update(factoid)
434+ event.session.add(factoid)
435 event.session.flush()
436 log.info(u"Creating factoid %s with name '%s' by %s", factoid.id, fname.name, event.identity)
437
438@@ -615,7 +615,7 @@
439 value = '%s %s' % (verb, value)
440 fvalue = FactoidValue(unicode(value), event.identity)
441 factoid.values.append(fvalue)
442- event.session.save_or_update(factoid)
443+ event.session.add(factoid)
444 event.session.commit()
445 self.last_set_factoid=factoid.names[0].name
446 log.info(u"Added value '%s' to factoid %s (%s) by %s/%s (%s)",
447@@ -676,7 +676,7 @@
448
449 oldvalue = factoid[2].value
450 factoid[2].value += suffix
451- event.session.save_or_update(factoid[2])
452+ event.session.add(factoid[2])
453 event.session.commit()
454
455 log.info(u"Appended '%s' to value %s (%s) of factoid %s (%s) by %s/%s (%s)",
456@@ -778,7 +778,7 @@
457 event.addresponse(u"That operation makes no sense. Try something like y/abcdef/ABCDEF/")
458 return
459
460- event.session.save_or_update(factoid[2])
461+ event.session.add(factoid[2])
462 event.session.commit()
463
464 log.info(u"Applying '%s' to value %s (%s) of factoid %s (%s) by %s/%s (%s)",
465
466=== modified file 'ibid/plugins/feeds.py'
467--- ibid/plugins/feeds.py 2011-04-05 00:31:49 +0000
468+++ ibid/plugins/feeds.py 2012-07-31 10:05:22 +0000
469@@ -147,7 +147,7 @@
470 return
471
472 feed = Feed(unicode(name), unicode(url), event.identity)
473- event.session.save(feed)
474+ event.session.add(feed)
475 event.session.commit()
476 event.addresponse(True)
477 log.info(u"Added feed '%s' by %s/%s (%s): %s (Found %s entries)",
478
479=== modified file 'ibid/plugins/fun.py'
480--- ibid/plugins/fun.py 2011-03-11 21:59:06 +0000
481+++ ibid/plugins/fun.py 2012-07-31 10:05:22 +0000
482@@ -393,7 +393,7 @@
483 raise EmptyBucketException
484
485 item.carried = False
486- session.save_or_update(item)
487+ session.add(item)
488
489 return item
490
491@@ -503,7 +503,7 @@
492 if items:
493 item = choice(items)
494 item.carried = False
495- event.session.save_or_update(item)
496+ event.session.add(item)
497
498 if kind == 'owned' and yours and yours != 'your':
499 item.determiner = yours
500@@ -623,6 +623,6 @@
501 else:
502 item = Item(object, None, event.identity)
503
504- event.session.save_or_update(item)
505+ event.session.add(item)
506
507 # vi: set et sta sw=4 ts=4:
508
509=== modified file 'ibid/plugins/identity.py'
510--- ibid/plugins/identity.py 2011-03-16 21:41:51 +0000
511+++ ibid/plugins/identity.py 2012-07-31 10:05:22 +0000
512@@ -54,7 +54,7 @@
513 return
514
515 account = Account(username)
516- event.session.save_or_update(account)
517+ event.session.add(account)
518 event.session.commit()
519 log.info(u"Created account %s (%s) by %s/%s (%s)",
520 account.id, account.username, event.account, event.identity, event.sender['connection'])
521@@ -64,14 +64,14 @@
522 .filter_by(identity=username, source=event.source).first()
523 if identity:
524 identity.account_id = account.id
525- event.session.save_or_update(identity)
526+ event.session.add(identity)
527 event.session.commit()
528 log.info(u"Attached identity %s (%s on %s) to account %s (%s)",
529 identity.id, identity.identity, identity.source, account.id, account.username)
530 else:
531 identity = event.session.query(Identity).get(event.identity)
532 identity.account_id = account.id
533- event.session.save_or_update(identity)
534+ event.session.add(identity)
535 event.session.commit()
536 log.info(u"Attached identity %s (%s on %s) to account %s (%s)",
537 identity.id, identity.identity, identity.source, account.id, account.username)
538@@ -132,7 +132,7 @@
539 oldname = account.username
540 account.username = newname
541
542- event.session.save_or_update(account)
543+ event.session.add(account)
544 event.session.commit()
545 identify_cache.clear()
546
547@@ -183,12 +183,12 @@
548 return
549
550 account = Account(username)
551- event.session.save_or_update(account)
552+ event.session.add(account)
553
554 currentidentity = event.session.query(Identity) \
555 .get(event.identity)
556 currentidentity.account_id = account.id
557- event.session.save_or_update(currentidentity)
558+ event.session.add(currentidentity)
559
560 identify_cache.clear()
561
562@@ -250,7 +250,7 @@
563 if not ident:
564 ident = Identity(source, identity)
565 ident.account_id = account.id
566- event.session.save_or_update(ident)
567+ event.session.add(ident)
568 event.session.commit()
569
570 identify_cache.clear()
571@@ -276,7 +276,7 @@
572 if not identity:
573 identity = Identity(source, user)
574 identity.account_id = account_id
575- event.session.save_or_update(identity)
576+ event.session.add(identity)
577 identify_cache.clear()
578
579 del self.tokens[token]
580@@ -308,7 +308,7 @@
581 event.addresponse(u"I don't know about that identity")
582 else:
583 identity.account_id = None
584- event.session.save_or_update(identity)
585+ event.session.add(identity)
586 event.session.commit()
587
588 identify_cache.clear()
589@@ -344,7 +344,7 @@
590 return
591
592 account.attributes.append(Attribute(name, value))
593- event.session.save_or_update(account)
594+ event.session.add(account)
595 event.session.commit()
596
597 event.addresponse(True)
598@@ -467,7 +467,7 @@
599 .first()
600 if not identity:
601 identity = Identity(event.source, event.sender['id'])
602- event.session.save_or_update(identity)
603+ event.session.add(identity)
604 try:
605 event.session.commit()
606 log.info(u'Created identity %s for %s on %s', identity.id, identity.identity, identity.source)
607@@ -546,7 +546,7 @@
608 credential = password
609
610 credential = Credential(method, credential, source, account.id)
611- event.session.save_or_update(credential)
612+ event.session.add(credential)
613 event.session.commit()
614 log.info(u"Added %s credential %s for account %s (%s) on %s by account %s",
615 method, credential.credential, account.id, account.username, source, event.account)
616@@ -605,7 +605,7 @@
617 return
618
619 permission.value = value
620- event.session.save_or_update(permission)
621+ event.session.add(permission)
622
623 event.session.commit()
624 ibid.auth.drop_caches()
625
626=== modified file 'ibid/plugins/karma.py'
627--- ibid/plugins/karma.py 2011-01-23 13:19:55 +0000
628+++ ibid/plugins/karma.py 2012-07-31 10:05:22 +0000
629@@ -133,7 +133,7 @@
630
631 event.session.delete(karma)
632 else:
633- event.session.save_or_update(karma)
634+ event.session.add(karma)
635 event.session.commit()
636
637 log.info(u"%s karma for '%s' by %s/%s (%s) because: %s",
638@@ -168,11 +168,18 @@
639
640 @match(r'^(reverse\s+)?karmaladder$')
641 def ladder(self, event, reverse):
642- karmas = event.session.query(Karma) \
643- .order_by(reverse and Karma.value.asc() or Karma.value.desc()) \
644- .limit(30).all()
645+ karmas = event.session.query(Karma)
646+ if reverse:
647+ karmas = karmas.order_by(Karma.value.asc())
648+ else:
649+ karmas = karmas.order_by(Karma.value.desc())
650+ karmas = karmas.limit(30).all()
651+
652 if karmas:
653- event.addresponse(', '.join(['%s: %s (%s)' % (karmas.index(karma), karma.subject, karma.value) for karma in karmas]))
654+ event.addresponse(u', '.join(
655+ u'%s: %s (%s)'
656+ % (karmas.index(karma), karma.subject, karma.value)
657+ for karma in karmas))
658 else:
659 event.addresponse(u"I don't really care about anything")
660
661
662=== modified file 'ibid/plugins/memo.py'
663--- ibid/plugins/memo.py 2011-03-23 16:11:13 +0000
664+++ ibid/plugins/memo.py 2012-07-31 10:05:22 +0000
665@@ -118,7 +118,7 @@
666 event.addresponse(u'I am not connected to %s', source)
667 return
668 to = Identity(source, who)
669- event.session.save(to)
670+ event.session.add(to)
671 event.session.commit()
672
673 log.info(u"Created identity %s for %s on %s", to.id, to.identity,
674@@ -133,7 +133,7 @@
675
676 memo = Memo(event.identity, to.id, memo,
677 how.lower() in (u'pm', u'privmsg', u'msg'))
678- event.session.save_or_update(memo)
679+ event.session.add(memo)
680
681 event.session.commit()
682 log.info(u"Stored memo %s for %s (%s) from %s (%s): %s",
683@@ -286,7 +286,7 @@
684 event.addresponse(message)
685
686 memo.delivered = True
687- event.session.save_or_update(memo)
688+ event.session.add(memo)
689 event.session.commit()
690 log.info(u"Delivered memo %s to %s (%s)",
691 memo.id, event.identity, event.sender['connection'])
692
693=== modified file 'ibid/plugins/seen.py'
694--- ibid/plugins/seen.py 2010-03-27 15:50:58 +0000
695+++ ibid/plugins/seen.py 2012-07-31 10:05:22 +0000
696@@ -86,7 +86,7 @@
697 sighting.time = event.time
698 sighting.count = sighting.count + 1
699
700- event.session.save_or_update(sighting)
701+ event.session.add(sighting)
702 try:
703 event.session.commit()
704 except IntegrityError:
705
706=== modified file 'ibid/plugins/urlgrab.py'
707--- ibid/plugins/urlgrab.py 2011-01-26 20:28:17 +0000
708+++ ibid/plugins/urlgrab.py 2012-07-31 10:05:22 +0000
709@@ -76,7 +76,7 @@
710 url = 'http://%s' % url
711
712 u = URL(url, event.channel, event.identity)
713- event.session.save_or_update(u)
714+ event.session.add(u)
715
716 if self.service and self.username:
717 self._post_url(event, url)
718
719=== modified file 'ibid/test/__init__.py'
720--- ibid/test/__init__.py 2011-08-14 15:26:08 +0000
721+++ ibid/test/__init__.py 2012-07-31 10:05:22 +0000
722@@ -10,6 +10,8 @@
723 import sys
724 import tempfile
725
726+import sqlalchemy
727+
728 from twisted.python import log
729 from twisted.python.modules import getModule
730 from twisted.trial import unittest
731@@ -103,6 +105,13 @@
732
733 def setUp(self):
734 super(PluginTestCase, self).setUp()
735+ if sqlalchemy.__version__ > '0.6.0':
736+ raise unittest.SkipTest(
737+ "PluginTestCase doesn't work with SQLAlchemy 0.6")
738+ if self.network and os.getenv('IBID_NETWORKLESS_TEST') is not None:
739+ raise unittest.SkipTest('test uses network')
740+
741+ ibid.config = FileConfig(locate_resource('ibid.test', 'test.ini'))
742
743 if self.load_configured is None:
744 self.load_configured = not self.load
745@@ -127,7 +136,7 @@
746 session = ibid.databases.ibid()
747
748 self.identity = Identity(self.source, self.username)
749- session.save(self.identity)
750+ session.add(self.identity)
751 session.commit()
752 self.identity = session.query(Identity) \
753 .filter_by(identity=self.username).one()
754
755=== modified file 'scripts/ibid-factpack'
756--- scripts/ibid-factpack 2010-02-16 09:41:11 +0000
757+++ scripts/ibid-factpack 2012-07-31 10:05:22 +0000
758@@ -85,7 +85,7 @@
759 exit(5)
760
761 factpack = Factpack(name)
762-session.save(factpack)
763+session.add(factpack)
764 session.flush()
765
766 existing = []
767@@ -102,7 +102,7 @@
768 fvalue = FactoidValue(unicode(value), None, factpack=factpack.id)
769 factoid.values.append(fvalue)
770 if len(factoid.names) > 0:
771- session.save(factoid)
772+ session.add(factoid)
773
774 if existing and not options.skip:
775 print >> stderr, u'The following factoids already exist in the database. ' \
776
777=== modified file 'scripts/ibid-knab-import'
778--- scripts/ibid-knab-import 2011-02-20 18:31:50 +0000
779+++ scripts/ibid-knab-import 2012-07-31 10:05:22 +0000
780@@ -130,7 +130,7 @@
781 if not identity:
782 identity = Identity(source, user)
783 identity.created = created
784- session.save(identity)
785+ session.add(identity)
786 session.flush()
787 elif identity.created > created:
788 identity.created = created
789@@ -187,7 +187,7 @@
790 fvalue.time = kfactoid.utc_time
791
792 factoid.values.append(fvalue)
793- ibid.save_or_update(factoid)
794+ ibid.add(factoid)
795
796 ibid.commit()
797
798@@ -297,7 +297,7 @@
799 config.merge(FileConfig('local.ini'))
800
801 ibidengine = create_engine(config.databases['ibid'], encoding='utf-8')
802- IbidSession = sessionmaker(bind=ibidengine, transactional=False)
803+ IbidSession = sessionmaker(bind=ibidengine, autocommit=True)
804 ibid = IbidSession()
805
806 import_factoids(knab, ibid, source)
807
808=== modified file 'scripts/ibid-plugin'
809--- scripts/ibid-plugin 2011-03-15 09:56:25 +0000
810+++ scripts/ibid-plugin 2012-07-31 10:05:22 +0000
811@@ -102,7 +102,7 @@
812 identity = session.query(Identity).filter_by(identity=username, source=u'test_source').first()
813 if not identity:
814 identity = Identity(u'test_source',username)
815- session.save(identity)
816+ session.add(identity)
817 session.commit()
818 identity = session.query(Identity).filter_by(identity=username).first()
819 identity_id = identity.id
820
821=== modified file 'scripts/ibid-setup'
822--- scripts/ibid-setup 2011-02-25 23:43:15 +0000
823+++ scripts/ibid-setup 2012-07-31 10:05:22 +0000
824@@ -158,8 +158,8 @@
825 credential = Credential(u'password', hash(unicode(pass1)))
826 account.credentials.append(credential)
827
828-session.save_or_update(account)
829-session.save_or_update(identity)
830+session.add(account)
831+session.add(identity)
832 session.commit()
833 session.close()
834
835
836=== modified file 'setup.py'
837--- setup.py 2010-09-26 22:55:15 +0000
838+++ setup.py 2012-07-31 10:05:22 +0000
839@@ -18,7 +18,7 @@
840 'PyStemmer',
841 'python-dateutil',
842 'SOAPpy',
843- 'SQLAlchemy>=0.5,<0.6a', # Works with >=0.4.6 except on OS X
844+ 'SQLAlchemy>=0.6',
845 'Twisted',
846 'wokkel>=0.6.3',
847 ]

Subscribers

People subscribed via source and target branches

to all changes: