Merge lp:~stefanor/ibid/sqlalchemy-0.6-trunk into lp:ibid
- sqlalchemy-0.6-trunk
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Stefano Rivera | ||||
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Keegan Carruthers-Smith | Approve | ||
Stefano Rivera | Approve | ||
Jonathan Hitchcock | Approve | ||
Max Rabkin | Approve | ||
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
Max Rabkin (max-rabkin) wrote : Posted in a previous version of this proposal | # |
Keegan Carruthers-Smith (keegan-csmith) wrote : Posted in a previous version of this proposal | # |
Don't know much about sqlalchemy, so gonna 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?
Keegan Carruthers-Smith (keegan-csmith) wrote : | # |
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.
Keegan Carruthers-Smith (keegan-csmith) wrote : | # |
by ibid, i mean tibid.
Ibid Branch Auto-Lander (ibid-tarmac) wrote : | # |
Voting does not meet specified criteria. Required: Approve >= 1, Disapprove == 0. Got: 2 Pending.
Ibid Branch Auto-Lander (ibid-tarmac) wrote : | # |
The attempt to merge lp:~stefanor/ibid/sqlalchemy-0.6-trunk into lp:ibid failed. Below is the output from the failed tests.
=======
[ERROR]: ibid
Traceback (most recent call last):
File "/usr/lib/
things.
File "/usr/lib/
return filenameToModul
File "/usr/lib/
ret = reflect.
File "/usr/lib/
topLevelPackage = _importAndCheck
File "/home/
import ibid.core
File "/home/
from ibid.db import SchemaVersionEx
File "/home/
from ibid.db.types import Integer, DateTime, Boolean, \
File "/home/
monkey_patch()
File "/home/
import sqlalchemy.
exceptions.
-------
FAILED (errors=1)
Traceback (most recent call last):
File "/usr/lib/
self.
File "/usr/lib/
self[
File "/usr/lib/
for p in plugin.
File "/usr/lib/
allDropins = getCache(package)
--- <exception caught here> ---
File "/usr/lib/
provider = pluginModule.load()
File "/usr/lib/
return self.pathEntry.
File "/usr/lib/
topLevelPackage = _importAndCheck
File "/home/
import ibid
File "/home/
import ibid.core
File "/home/
from ibid.db import SchemaVersionEx
File "/home/
from ibid.db.types import Integer, DateTime, Boolean, \
...
Ibid Branch Auto-Lander (ibid-tarmac) wrote : | # |
Attempt to merge into lp:ibid failed due to conflicts:
text conflict in ibid/test/
Ibid Branch Auto-Lander (ibid-tarmac) wrote : | # |
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
Keegan Carruthers-Smith (keegan-csmith) wrote : | # |
blind approvals ftw
Preview Diff
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 | ] |
bucket now uses the database