Make pokedex work with SQLAlchemy 0.7. Warning: ugly hack! encukou-sqla-0.7
authorPetr Viktorin <encukou@gmail.com>
Wed, 13 Apr 2011 15:43:34 +0000 (18:43 +0300)
committerPetr Viktorin <encukou@gmail.com>
Wed, 13 Apr 2011 15:43:34 +0000 (18:43 +0300)
In its quest to reduce the number of calls, SQLAlchemy 0.7 sometimes
bypasses session.execute, where the _default_language_id bound parameter
was set.

Monkeypatching the connection works for now, but I hope there's a better
way (see multilang.py).

pokedex/db/load.py
pokedex/db/markdown.py
pokedex/db/multilang.py
setup.py

index d307fd8..d0dc00b 100644 (file)
@@ -4,7 +4,6 @@ import fnmatch
 import os.path
 import sys
 
 import os.path
 import sys
 
-from sqlalchemy.orm.attributes import instrumentation_registry
 import sqlalchemy.sql.util
 import sqlalchemy.types
 
 import sqlalchemy.sql.util
 import sqlalchemy.types
 
index 1ad304c..c9fd9a7 100644 (file)
@@ -12,7 +12,7 @@ spline-pokedex.
 from __future__ import absolute_import
 
 import markdown
 from __future__ import absolute_import
 
 import markdown
-import sqlalchemy.types
+import sqlalchemy
 
 class MarkdownString(object):
     """Wraps a Markdown string.  Stringifies to the original text, but .as_html
 
 class MarkdownString(object):
     """Wraps a Markdown string.  Stringifies to the original text, but .as_html
@@ -103,7 +103,7 @@ class MoveEffectPropertyMap(MoveEffectProperty):
             newdict[key] = _markdownify_effect_text(obj, newdict[key])
         return newdict
 
             newdict[key] = _markdownify_effect_text(obj, newdict[key])
         return newdict
 
-class MarkdownColumn(sqlalchemy.types.TypeDecorator):
+class MarkdownColumn(sqlalchemy.TypeDecorator):
     """Generic SQLAlchemy column type for Markdown text.
 
     Do NOT use this for move effects!  They need to know what move they belong
     """Generic SQLAlchemy column type for Markdown text.
 
     Do NOT use this for move effects!  They need to know what move they belong
index 7e2840f..d027d13 100644 (file)
@@ -5,8 +5,9 @@ from sqlalchemy.orm import aliased, compile_mappers, mapper, relationship, synon
 from sqlalchemy.orm.collections import attribute_mapped_collection
 from sqlalchemy.orm.scoping import ScopedSession
 from sqlalchemy.orm.session import Session, object_session
 from sqlalchemy.orm.collections import attribute_mapped_collection
 from sqlalchemy.orm.scoping import ScopedSession
 from sqlalchemy.orm.session import Session, object_session
+from sqlalchemy.engine.base import Connection
 from sqlalchemy.schema import Column, ForeignKey, Table
 from sqlalchemy.schema import Column, ForeignKey, Table
-from sqlalchemy.sql.expression import and_, bindparam, select
+from sqlalchemy.sql.expression import and_, bindparam, select, Select
 from sqlalchemy.types import Integer
 
 def create_translation_table(_table_name, foreign_class, relation_name,
 from sqlalchemy.types import Integer
 
 def create_translation_table(_table_name, foreign_class, relation_name,
@@ -167,20 +168,24 @@ class MultilangSession(Session):
 
         super(MultilangSession, self).__init__(*args, **kwargs)
 
 
         super(MultilangSession, self).__init__(*args, **kwargs)
 
-    def execute(self, clause, params=None, *args, **kwargs):
-        if not params:
-            params = {}
-        params.setdefault('_default_language_id', self.default_language_id)
-
-        return super(MultilangSession, self).execute(
-            clause, params, *args, **kwargs)
+    def connection(self, *args, **kwargs):
+        """Monkeypatch the connection. Not pretty at all.
+        """
+        conn = super(MultilangSession, self).connection(*args, **kwargs)
+        original_execute = conn.execute
+        if original_execute.__name__ != 'monkeypatched_execute':
+            def monkeypatched_execute(statement, *multiparams, **params):
+                if isinstance(statement, Select):
+                    boundparams = dict(multiparams[0])
+                    boundparams.setdefault('_default_language_id', self.default_language_id)
+                    multiparams = [boundparams] + list(multiparams[1:])
+                return original_execute(statement, *multiparams, **params)
+            conn.execute = monkeypatched_execute
+        return conn
 
 class MultilangScopedSession(ScopedSession):
     """Dispatches language selection to the attached Session."""
 
 
 class MultilangScopedSession(ScopedSession):
     """Dispatches language selection to the attached Session."""
 
-    def __init__(self, *args, **kwargs):
-        super(MultilangScopedSession, self).__init__(*args, **kwargs)
-
     @property
     def default_language_id(self):
         """Passes the new default language id through to the current session.
     @property
     def default_language_id(self):
         """Passes the new default language id through to the current session.
index 3bc7028..2f5887e 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@ setup(
         'pokedex': ['data/csv/*.csv']
     },
     install_requires=[
         'pokedex': ['data/csv/*.csv']
     },
     install_requires=[
-        'SQLAlchemy>=0.6.6',
+        'SQLAlchemy>=0.7.0b3',
         'whoosh>=1.1.0',
         'markdown',
         'construct',
         'whoosh>=1.1.0',
         'markdown',
         'construct',