summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2013-11-21 13:30:32 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2013-11-21 13:30:32 -0500
commit2aa00c49d7a1a783ff50832f2de7760bfaaccf6d (patch)
tree8cee77853374a0570c562e1b5510bb55da3290ce
parent42fd77a4bfb8c5a1c02c89a17481a90cd039f10e (diff)
downloadsqlalchemy-2aa00c49d7a1a783ff50832f2de7760bfaaccf6d.tar.gz
- Fixed bug which prevented the ``serializer`` extension from working
correctly with table or column names that contain non-ASCII characters. [ticket:2869]
-rw-r--r--doc/build/changelog/changelog_08.rst9
-rw-r--r--lib/sqlalchemy/ext/serializer.py8
-rw-r--r--lib/sqlalchemy/sql/selectable.py2
-rw-r--r--lib/sqlalchemy/testing/assertions.py2
-rw-r--r--test/ext/test_serializer.py24
5 files changed, 36 insertions, 9 deletions
diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst
index 3a5844bbb..dde98e82f 100644
--- a/doc/build/changelog/changelog_08.rst
+++ b/doc/build/changelog/changelog_08.rst
@@ -12,6 +12,15 @@
:version: 0.8.4
.. change::
+ :tags: bug, ext
+ :tickets: 2869
+ :versions: 0.9.0b2
+
+ Fixed bug which prevented the ``serializer`` extension from working
+ correctly with table or column names that contain non-ASCII
+ characters.
+
+ .. change::
:tags: bug, orm
:tickets: 2818
:versions: 0.9.0b2
diff --git a/lib/sqlalchemy/ext/serializer.py b/lib/sqlalchemy/ext/serializer.py
index 8abd1fdf3..672e077ad 100644
--- a/lib/sqlalchemy/ext/serializer.py
+++ b/lib/sqlalchemy/ext/serializer.py
@@ -58,7 +58,7 @@ from ..orm.interfaces import MapperProperty
from ..orm.attributes import QueryableAttribute
from .. import Table, Column
from ..engine import Engine
-from ..util import pickle, byte_buffer, b64encode, b64decode
+from ..util import pickle, byte_buffer, b64encode, b64decode, text_type
import re
@@ -80,9 +80,9 @@ def Serializer(*args, **kw):
id = "mapperprop:" + b64encode(pickle.dumps(obj.parent.class_)) + \
":" + obj.key
elif isinstance(obj, Table):
- id = "table:" + str(obj)
+ id = "table:" + text_type(obj.key)
elif isinstance(obj, Column) and isinstance(obj.table, Table):
- id = "column:" + str(obj.table) + ":" + obj.key
+ id = "column:" + text_type(obj.table.key) + ":" + text_type(obj.key)
elif isinstance(obj, Session):
id = "session:"
elif isinstance(obj, Engine):
@@ -112,7 +112,7 @@ def Deserializer(file, metadata=None, scoped_session=None, engine=None):
return None
def persistent_load(id):
- m = our_ids.match(str(id))
+ m = our_ids.match(text_type(id))
if not m:
return None
else:
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 046840110..708103fc6 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -246,7 +246,7 @@ class FromClause(Selectable):
:param column: the target :class:`.ColumnElement` to be matched
:param require_embedded: only return corresponding columns for
- the given :class:`.ColumnElement`, if the given :class:`.ColumnElement`
+ the given :class:`.ColumnElement`, if the given :class:`.ColumnElement`
is actually present within a sub-element
of this :class:`.FromClause`. Normally the column will match if
it merely shares a common ancestor with one of the exported
diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py
index 8a859c0b1..ebd1b424d 100644
--- a/lib/sqlalchemy/testing/assertions.py
+++ b/lib/sqlalchemy/testing/assertions.py
@@ -235,7 +235,7 @@ class AssertsCompiledSQL(object):
if util.py3k:
param_str = param_str.encode('utf-8').decode('ascii', 'ignore')
- print("\nSQL String:\n" + util.text_type(c) + param_str)
+ print("\nSQL String:\n" + util.text_type(c).encode('utf-8') + param_str)
cc = re.sub(r'[\n\t]', '', util.text_type(c))
diff --git a/test/ext/test_serializer.py b/test/ext/test_serializer.py
index 1950bd2d1..ffeac55c1 100644
--- a/test/ext/test_serializer.py
+++ b/test/ext/test_serializer.py
@@ -1,13 +1,15 @@
+# coding: utf-8
from sqlalchemy.ext import serializer
from sqlalchemy import testing
from sqlalchemy import Integer, String, ForeignKey, select, \
- desc, func, util
+ desc, func, util, MetaData
from sqlalchemy.testing.schema import Table
from sqlalchemy.testing.schema import Column
from sqlalchemy.orm import relationship, sessionmaker, scoped_session, \
class_mapper, mapper, joinedload, configure_mappers, aliased
-from sqlalchemy.testing import eq_
+from sqlalchemy.testing import eq_, AssertsCompiledSQL
+from sqlalchemy.util import u, ue
from sqlalchemy.testing import fixtures
@@ -19,7 +21,7 @@ class Address(fixtures.ComparableEntity):
users = addresses = Session = None
-class SerializeTest(fixtures.MappedTest):
+class SerializeTest(AssertsCompiledSQL, fixtures.MappedTest):
run_setup_mappers = 'once'
run_inserts = 'once'
@@ -171,6 +173,22 @@ class SerializeTest(fixtures.MappedTest):
x = serializer.loads(ser, users.metadata)
eq_(str(r), str(x))
+ def test_unicode(self):
+ m = MetaData()
+ t = Table(ue('\u6e2c\u8a66'), m,
+ Column(ue('\u6e2c\u8a66_id'), Integer))
+
+ expr = select([t]).where(t.c[ue('\u6e2c\u8a66_id')] == 5)
+
+ expr2 = serializer.loads(serializer.dumps(expr, -1), m)
+
+ self.assert_compile(
+ expr2,
+ ue('SELECT "\u6e2c\u8a66"."\u6e2c\u8a66_id" FROM "\u6e2c\u8a66" '
+ 'WHERE "\u6e2c\u8a66"."\u6e2c\u8a66_id" = :\u6e2c\u8a66_id_1'),
+ dialect="default"
+ )
+
if __name__ == '__main__':
testing.main()