summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2016-02-21 20:52:43 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2016-02-21 20:52:43 -0500
commit01809bddff5b6e93010eb139aed54526c6e6c058 (patch)
treee8a31670e7dffdce04802de112edc2f7ea563e1c
parent6713817e1186cd1e36c9aea9d89a30bc299ffe27 (diff)
downloadsqlalchemy-01809bddff5b6e93010eb139aed54526c6e6c058.tar.gz
- Fixed bug in "to_list" conversion where a single bytes object
would be turned into a list of individual characters. This would impact among other things using the :meth:`.Query.get` method on a primary key that's a bytes object. fixes #3660
-rw-r--r--doc/build/changelog/changelog_10.rst9
-rw-r--r--lib/sqlalchemy/util/_collections.py6
-rw-r--r--lib/sqlalchemy/util/compat.py2
-rw-r--r--test/base/test_utils.py16
4 files changed, 30 insertions, 3 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index fa1be4c16..36152c236 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -19,6 +19,15 @@
:version: 1.0.13
.. change::
+ :tags: bug, py3k
+ :tickets: 3660
+
+ Fixed bug in "to_list" conversion where a single bytes object
+ would be turned into a list of individual characters. This would
+ impact among other things using the :meth:`.Query.get` method
+ on a primary key that's a bytes object.
+
+ .. change::
:tags: bug, orm
:tickets: 3658
diff --git a/lib/sqlalchemy/util/_collections.py b/lib/sqlalchemy/util/_collections.py
index ed1a3e471..c29b81f6a 100644
--- a/lib/sqlalchemy/util/_collections.py
+++ b/lib/sqlalchemy/util/_collections.py
@@ -10,7 +10,8 @@
from __future__ import absolute_import
import weakref
import operator
-from .compat import threading, itertools_filterfalse, string_types
+from .compat import threading, itertools_filterfalse, string_types, \
+ binary_types
from . import py2k
import types
import collections
@@ -794,7 +795,8 @@ def coerce_generator_arg(arg):
def to_list(x, default=None):
if x is None:
return default
- if not isinstance(x, collections.Iterable) or isinstance(x, string_types):
+ if not isinstance(x, collections.Iterable) or \
+ isinstance(x, string_types + binary_types):
return [x]
elif isinstance(x, list):
return x
diff --git a/lib/sqlalchemy/util/compat.py b/lib/sqlalchemy/util/compat.py
index 99b5177b5..ee4a20f9b 100644
--- a/lib/sqlalchemy/util/compat.py
+++ b/lib/sqlalchemy/util/compat.py
@@ -62,6 +62,7 @@ if py3k:
)
string_types = str,
+ binary_types = bytes,
binary_type = bytes
text_type = str
int_types = int,
@@ -115,6 +116,7 @@ else:
from cStringIO import StringIO as byte_buffer
string_types = basestring,
+ binary_types = bytes,
binary_type = str
text_type = unicode
int_types = int, long
diff --git a/test/base/test_utils.py b/test/base/test_utils.py
index 53dbc12f9..fcb9a59a3 100644
--- a/test/base/test_utils.py
+++ b/test/base/test_utils.py
@@ -7,7 +7,7 @@ from sqlalchemy.testing import eq_, is_, ne_, fails_if, mock, expect_warnings
from sqlalchemy.testing.util import picklers, gc_collect
from sqlalchemy.util import classproperty, WeakSequence, get_callable_argspec
from sqlalchemy.sql import column
-from sqlalchemy.util import langhelpers
+from sqlalchemy.util import langhelpers, compat
import inspect
@@ -412,6 +412,20 @@ class ToListTest(fixtures.TestBase):
[1, 2, 3]
)
+ def test_from_bytes(self):
+
+ eq_(
+ util.to_list(compat.b('abc')),
+ [compat.b('abc')]
+ )
+
+ eq_(
+ util.to_list([
+ compat.b('abc'), compat.b('def')]),
+ [compat.b('abc'), compat.b('def')]
+ )
+
+
class ColumnCollectionTest(fixtures.TestBase):
def test_in(self):