From: Mike Bayer Date: Sat, 5 Sep 2009 03:29:20 +0000 (+0000) Subject: - the Binary type now returns data as a Python string X-Git-Tag: rel_0_6beta1~300 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0b292e8842851dd0ebb127ab1cd6131eefa288fe;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - the Binary type now returns data as a Python string (or a "bytes" type in Python 3), instead of the built- in "buffer" type. This allows symmetric round trips of binary data. [ticket:1524] --- diff --git a/CHANGES b/CHANGES index e2bd8f8933..68dd7cbe02 100644 --- a/CHANGES +++ b/CHANGES @@ -85,6 +85,11 @@ CHANGES - the last_inserted_ids() method has been renamed to the descriptor "inserted_primary_key". + - the Binary type now returns data as a Python string + (or a "bytes" type in Python 3), instead of the built- + in "buffer" type. This allows symmetric round trips + of binary data. [ticket:1524] + - User-defined "default" and "onupdate" callables which accept a context should now call upon "context.current_parameters" to get at the dictionary diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 4700a7b4ff..aa616efdf3 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -301,13 +301,7 @@ class _StringType(sqltypes.String): class _BinaryType(sqltypes.Binary): """Base for MySQL binary types.""" - def result_processor(self, dialect): - def process(value): - if value is None: - return None - else: - return util.buffer(value) - return process + pass class NUMERIC(_NumericType, sqltypes.NUMERIC): """MySQL NUMERIC type.""" diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 1b2c72bc7d..8b847f2014 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -778,6 +778,14 @@ class Binary(TypeEngine): return None return process + def result_processor(self, dialect): + def process(value): + if value is not None: + return str(value) + else: + return None + return process + def adapt(self, impltype): return impltype(length=self.length) diff --git a/test/orm/test_unitofwork.py b/test/orm/test_unitofwork.py index 4d2056b264..cdf6d39b94 100644 --- a/test/orm/test_unitofwork.py +++ b/test/orm/test_unitofwork.py @@ -304,7 +304,41 @@ class UnicodeSchemaTest(engine_base.AltEngineTest, _base.MappedTest): eq_([A(b=5), B(e=7)], session.query(A).all()) +class BinaryHistTest(_base.MappedTest, testing.AssertsExecutionResults): + @classmethod + def define_tables(cls, metadata): + Table('t1', metadata, + Column('id', sa.Integer, primary_key=True), + Column('data', sa.Binary), + ) + + @classmethod + def setup_classes(cls): + class Foo(_base.BasicEntity): + pass + @testing.resolve_artifact_names + def test_binary_equality(self): + + mapper(Foo, t1) + + s = create_session() + + f1 = Foo(data="this is some data") + s.add(f1) + s.flush() + s.expire_all() + f1 = s.query(Foo).first() + assert f1.data == "this is some data" + f1.data = "this is some data" + eq_( + sa.orm.attributes.get_history(f1, "data"), + ((), ["this is some data"], ()) + ) + def go(): + s.flush() + self.assert_sql_count(testing.db, go, 0) + class MutableTypesTest(_base.MappedTest): @classmethod diff --git a/test/sql/test_types.py b/test/sql/test_types.py index cede11cc5f..f57347115e 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -401,21 +401,29 @@ class BinaryTest(TestBase, AssertsExecutionResults): for stmt in ( binary_table.select(order_by=binary_table.c.primary_id), - text("select * from binary_table order by binary_table.primary_id", typemap={'pickled':PickleType, 'mypickle':MyPickleType}, bind=testing.db) + text( + "select * from binary_table order by binary_table.primary_id", + typemap={'pickled':PickleType, 'mypickle':MyPickleType, 'data':Binary, 'data_slice':Binary}, + bind=testing.db) ): - eq_data = lambda x, y: eq_(list(x), list(y)) - if util.jython: - _eq_data = eq_data - def eq_data(x, y): - # Jython currently returns arrays - from array import ArrayType - if isinstance(y, ArrayType): - return eq_(x, y.tostring()) - return _eq_data(x, y) + #if util.jython: + # TODO: may need to modify Binary type directly + # to detect jython if something other than str()/bytes() + # is needed to convert from raw to string/bytes. + # ArrayType should no longer be expected here though. + # users who want raw ArrayType can of course create their + # own BinaryType that does no conversion. + #_eq_data = eq_data + #def eq_data(x, y): + # # Jython currently returns arrays + # from array import ArrayType + # if isinstance(y, ArrayType): + # return eq_(x, y.tostring()) + # return _eq_data(x, y) l = stmt.execute().fetchall() - eq_data(stream1, l[0]['data']) - eq_data(stream1[0:100], l[0]['data_slice']) - eq_data(stream2, l[1]['data']) + eq_(stream1, l[0]['data']) + eq_(stream1[0:100], l[0]['data_slice']) + eq_(stream2, l[1]['data']) eq_(testobj1, l[0]['pickled']) eq_(testobj2, l[1]['pickled']) eq_(testobj3.moredata, l[0]['mypickle'].moredata)