[Sqlalchemy-commits] [1358] sqlalchemy/branches/schema/test: merged changes from trunk 1355-1357, re
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-29 17:16:29
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1358] sqlalchemy/branches/schema/test: merged changes from trunk 1355-1357, re: types, unit test qualifiers</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1358</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-29 12:16:16 -0500 (Sat, 29 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>merged changes from trunk 1355-1357, re: types, unit test qualifiers</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemydatabasesmysqlpy">sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemytypespy">sqlalchemy/branches/schema/lib/sqlalchemy/types.py</a></li> <li><a href="#sqlalchemybranchesschematestdefaultspy">sqlalchemy/branches/schema/test/defaults.py</a></li> <li><a href="#sqlalchemybranchesschematestinheritancepy">sqlalchemy/branches/schema/test/inheritance.py</a></li> <li><a href="#sqlalchemybranchesschematestobjectstorepy">sqlalchemy/branches/schema/test/objectstore.py</a></li> <li><a href="#sqlalchemybranchesschematestselectresultspy">sqlalchemy/branches/schema/test/selectresults.py</a></li> <li><a href="#sqlalchemybranchesschematesttestbasepy">sqlalchemy/branches/schema/test/testbase.py</a></li> <li><a href="#sqlalchemybranchesschematesttesttypespy">sqlalchemy/branches/schema/test/testtypes.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemydatabasesmysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/lib/sqlalchemy/databases/mysql.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -79,6 +79,11 @@ </span><span class="cx"> return "BINARY(%d)" % self.length </span><span class="cx"> else: </span><span class="cx"> return "BLOB" </span><ins>+ def convert_result_value(self, value, engine): + if value is None: + return None + else: + return buffer(value) </ins><span class="cx"> </span><span class="cx"> class MSBoolean(sqltypes.Boolean): </span><span class="cx"> def get_col_spec(self): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemytypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/types.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/types.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/lib/sqlalchemy/types.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -12,14 +12,13 @@ </span><span class="cx"> ] </span><span class="cx"> </span><span class="cx"> import sqlalchemy.util as util </span><ins>+import sqlalchemy.exceptions as exceptions </ins><span class="cx"> try: </span><span class="cx"> import cPickle as pickle </span><span class="cx"> except: </span><span class="cx"> import pickle </span><span class="cx"> </span><del>-class TypeEngine(object): - def __init__(self, *args, **kwargs): - pass </del><ins>+class AbstractType(object): </ins><span class="cx"> def _get_impl_dict(self): </span><span class="cx"> try: </span><span class="cx"> return self._impl_dict </span><span class="lines">@@ -27,6 +26,11 @@ </span><span class="cx"> self._impl_dict = {} </span><span class="cx"> return self._impl_dict </span><span class="cx"> impl_dict = property(_get_impl_dict) </span><ins>+ + +class TypeEngine(AbstractType): + def __init__(self, *args, **params): + pass </ins><span class="cx"> def engine_impl(self, engine): </span><span class="cx"> return self.dialect_impl(engine.dialect) </span><span class="cx"> def dialect_impl(self, dialect): </span><span class="lines">@@ -43,18 +47,42 @@ </span><span class="cx"> self._impl = impl </span><span class="cx"> impl = property(_get_impl, _set_impl) </span><span class="cx"> def get_col_spec(self): </span><ins>+ raise NotImplementedError() + def convert_bind_param(self, value, engine): + return value + def convert_result_value(self, value, engine): + return value + def adapt(self, cls): + return cls() + + +class TypeDecorator(AbstractType): + def __init__(self, *args, **kwargs): + if not hasattr(self.__class__, 'impl'): + raise exceptions.AssertionError("TypeDecorator implementations require a class-level variable 'impl' which refers to the class of type being decorated") + self.impl = self.__class__.impl(*args, **kwargs) + def engine_impl(self, engine): + return self.dialect_impl(engine.dialect) + def dialect_impl(self, dialect): + try: + return self.impl_dict[dialect] + except: + typedesc = dialect.type_descriptor(self.impl) + tt = self.copy() + if not isinstance(tt, self.__class__): + raise exceptions.AssertionError("Type object %s does not properly implement the copy() method, it must return an object of type %s" % (self, self.__class__)) + tt.impl = typedesc + self.impl_dict[dialect] = tt + return tt + def get_col_spec(self): </ins><span class="cx"> return self.impl.get_col_spec() </span><span class="cx"> def convert_bind_param(self, value, dialect): </span><span class="cx"> return self.impl.convert_bind_param(value, dialect) </span><span class="cx"> def convert_result_value(self, value, dialect): </span><span class="cx"> return self.impl.convert_result_value(value, dialect) </span><del>- def set_impl(self, impltype): - self.impl = impltype(**self.get_constructor_args()) - def get_constructor_args(self): - return {} - def adapt_args(self): - return self - </del><ins>+ def copy(self): + raise NotImplementedError() + </ins><span class="cx"> def to_instance(typeobj): </span><span class="cx"> if typeobj is None: </span><span class="cx"> return NULLTYPE </span><span class="lines">@@ -65,8 +93,7 @@ </span><span class="cx"> def adapt_type(typeobj, colspecs): </span><span class="cx"> if isinstance(typeobj, type): </span><span class="cx"> typeobj = typeobj() </span><del>- t2 = typeobj.adapt_args() - for t in t2.__class__.__mro__[0:-1]: </del><ins>+ for t in typeobj.__class__.__mro__[0:-1]: </ins><span class="cx"> try: </span><span class="cx"> impltype = colspecs[t] </span><span class="cx"> break </span><span class="lines">@@ -75,9 +102,7 @@ </span><span class="cx"> else: </span><span class="cx"> # couldnt adapt...raise exception ? </span><span class="cx"> return typeobj </span><del>- typeobj.set_impl(impltype) - typeobj.impl.impl = NULLTYPE - return typeobj </del><ins>+ return typeobj.adapt(impltype) </ins><span class="cx"> </span><span class="cx"> class NullTypeEngine(TypeEngine): </span><span class="cx"> def get_col_spec(self): </span><span class="lines">@@ -87,16 +112,17 @@ </span><span class="cx"> def convert_result_value(self, value, dialect): </span><span class="cx"> return value </span><span class="cx"> </span><del>-class TypeDecorator(object): - """TypeDecorator is deprecated""" - pass </del><span class="cx"> </span><del>- </del><span class="cx"> class String(TypeEngine): </span><ins>+ def __new__(cls, *args, **kwargs): + if cls is not String or len(args) > 0 or kwargs.has_key('length'): + return super(String, cls).__new__(cls, *args, **kwargs) + else: + return super(String, TEXT).__new__(TEXT, *args, **kwargs) </ins><span class="cx"> def __init__(self, length = None): </span><span class="cx"> self.length = length </span><del>- def get_constructor_args(self): - return {'length':self.length} </del><ins>+ def adapt(self, impltype): + return impltype(length=self.length) </ins><span class="cx"> def convert_bind_param(self, value, dialect): </span><span class="cx"> if not dialect.convert_unicode or value is None or not isinstance(value, unicode): </span><span class="cx"> return value </span><span class="lines">@@ -107,13 +133,9 @@ </span><span class="cx"> return value </span><span class="cx"> else: </span><span class="cx"> return value.decode(dialect.encoding) </span><del>- def adapt_args(self): - if self.length is None: - return TEXT() - else: - return self </del><span class="cx"> </span><del>-class Unicode(String): </del><ins>+class Unicode(TypeDecorator): + impl = String </ins><span class="cx"> def convert_bind_param(self, value, dialect): </span><span class="cx"> if value is not None and isinstance(value, unicode): </span><span class="cx"> return value.encode(dialect.encoding) </span><span class="lines">@@ -124,7 +146,9 @@ </span><span class="cx"> return value.decode(dialect.encoding) </span><span class="cx"> else: </span><span class="cx"> return value </span><del>- </del><ins>+ def copy(self): + return Unicode(self.impl.length) + </ins><span class="cx"> class Integer(TypeEngine): </span><span class="cx"> """integer datatype""" </span><span class="cx"> pass </span><span class="lines">@@ -138,49 +162,57 @@ </span><span class="cx"> def __init__(self, precision = 10, length = 2): </span><span class="cx"> self.precision = precision </span><span class="cx"> self.length = length </span><del>- def get_constructor_args(self): - return {'precision':self.precision, 'length':self.length} </del><ins>+ def adapt(self, impltype): + return impltype(precision=self.precision, length=self.length) </ins><span class="cx"> </span><span class="cx"> class Float(Numeric): </span><span class="cx"> def __init__(self, precision = 10): </span><span class="cx"> self.precision = precision </span><del>- def get_constructor_args(self): - return {'precision':self.precision} </del><ins>+ def adapt(self, impltype): + return impltype(precision=self.precision) </ins><span class="cx"> </span><span class="cx"> class DateTime(TypeEngine): </span><ins>+ """implements a type for datetime.datetime() objects""" </ins><span class="cx"> pass </span><span class="cx"> </span><span class="cx"> class Date(TypeEngine): </span><ins>+ """implements a type for datetime.date() objects""" </ins><span class="cx"> pass </span><span class="cx"> </span><span class="cx"> class Time(TypeEngine): </span><ins>+ """implements a type for datetime.time() objects""" </ins><span class="cx"> pass </span><span class="cx"> </span><span class="cx"> class Binary(TypeEngine): </span><span class="cx"> def __init__(self, length=None): </span><span class="cx"> self.length = length </span><span class="cx"> def convert_bind_param(self, value, dialect): </span><del>- return dialect.dbapi().Binary(value) </del><ins>+ if value is not None: + return dialect.dbapi().Binary(value) + else: + return None </ins><span class="cx"> def convert_result_value(self, value, dialect): </span><span class="cx"> return value </span><del>- def get_constructor_args(self): - return {'length':self.length} </del><ins>+ def adapt(self, impltype): + return impltype(length=self.length) </ins><span class="cx"> </span><del>-class PickleType(Binary): - def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): - """allows the pickle protocol to be specified""" - self.protocol = protocol - def convert_result_value(self, value, dialect): - if value is None: - return None - buf = Binary.convert_result_value(self, value, dialect) - return pickle.loads(str(buf)) - def convert_bind_param(self, value, dialect): - if value is None: - return None - return Binary.convert_bind_param(self, pickle.dumps(value, self.protocol), dialect) - def get_constructor_args(self): - return {} </del><ins>+class PickleType(TypeDecorator): + impl = Binary + def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): + """allows the pickle protocol to be specified""" + self.protocol = protocol + super(PickleType, self).__init__() + def convert_result_value(self, value, dialect): + if value is None: + return None + buf = self.impl.convert_result_value(value, dialect) + return pickle.loads(str(buf)) + def convert_bind_param(self, value, dialect): + if value is None: + return None + return self.impl.convert_bind_param(pickle.dumps(value, self.protocol), dialect) + def copy(self): + return PickleType(self.protocol) </ins><span class="cx"> </span><span class="cx"> class Boolean(TypeEngine): </span><span class="cx"> pass </span></span></pre></div> <a id="sqlalchemybranchesschematestdefaultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/defaults.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/defaults.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/defaults.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -132,7 +132,8 @@ </span><span class="cx"> ) </span><span class="cx"> </span><span class="cx"> cartitems.create() </span><del>- </del><ins>+ + @testbase.supported('postgres', 'oracle') </ins><span class="cx"> def testsequence(self): </span><span class="cx"> cartitems.insert().execute(description='hi') </span><span class="cx"> cartitems.insert().execute(description='there') </span><span class="lines">@@ -141,6 +142,7 @@ </span><span class="cx"> cartitems.select().execute().fetchall() </span><span class="cx"> </span><span class="cx"> </span><ins>+ @testbase.supported('postgres', 'oracle') </ins><span class="cx"> def teststandalone(self): </span><span class="cx"> s = Sequence("my_sequence", metadata=testbase.db) </span><span class="cx"> s.create() </span><span class="lines">@@ -150,6 +152,7 @@ </span><span class="cx"> finally: </span><span class="cx"> s.drop() </span><span class="cx"> </span><ins>+ @testbase.supported('postgres', 'oracle') </ins><span class="cx"> def teststandalone2(self): </span><span class="cx"> x = cartitems.c.cart_id.sequence.execute() </span><span class="cx"> self.assert_(1 <= x <= 4) </span></span></pre></div> <a id="sqlalchemybranchesschematestinheritancepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/inheritance.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/inheritance.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/inheritance.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -383,6 +383,21 @@ </span><span class="cx"> #contents.add_property('content_type', relation(content_types)) #adding this makes the inheritance stop working </span><span class="cx"> # shouldnt throw exception </span><span class="cx"> products = mapper(Product, product, inherits=contents) </span><ins>+ + def testbackref(self): + """this test is currently known to fail in the 0.1 series of SQLAlchemy, pending the resolution of [ticket:154]""" + class ContentType(object): pass + class Content(object): pass + class Product(Content): pass + + # this test fails currently + contents = mapper(Content, content) + products = mapper(Product, product, inherits=contents) + content_types = mapper(ContentType, content_type, properties={ + 'content':relation(contents, backref='contenttype') + }) + p = Product() + p.contenttype = ContentType() </ins><span class="cx"> </span><span class="cx"> class InheritTest6(testbase.AssertMixin): </span><span class="cx"> """tests eager load/lazy load of child items off inheritance mappers, tests that </span></span></pre></div> <a id="sqlalchemybranchesschematestobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/objectstore.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/objectstore.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/objectstore.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -90,7 +90,8 @@ </span><span class="cx"> version_table.delete().execute() </span><span class="cx"> objectstore.clear() </span><span class="cx"> clear_mappers() </span><del>- </del><ins>+ + @testbase.unsupported('mysql') </ins><span class="cx"> def testbasic(self): </span><span class="cx"> s = Session() </span><span class="cx"> class Foo(object):pass </span><span class="lines">@@ -197,6 +198,8 @@ </span><span class="cx"> def setUp(self): </span><span class="cx"> objectstore.clear() </span><span class="cx"> clear_mappers() </span><ins>+ + @testbase.unsupported('sqlite') </ins><span class="cx"> def testprimarykey(self): </span><span class="cx"> class Entry(object): </span><span class="cx"> pass </span><span class="lines">@@ -496,7 +499,7 @@ </span><span class="cx"> usersaddresses = sql.join(users, addresses, users.c.user_id == addresses.c.user_id) </span><span class="cx"> print usersaddresses._get_col_by_original(users.c.user_id) </span><span class="cx"> print repr(usersaddresses._orig_cols) </span><del>- m = mapper(User, usersaddresses, primarytable = users, </del><ins>+ m = mapper(User, usersaddresses, </ins><span class="cx"> properties = dict( </span><span class="cx"> email = addresses.c.email_address, </span><span class="cx"> foo_id = [users.c.user_id, addresses.c.user_id], </span></span></pre></div> <a id="sqlalchemybranchesschematestselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/selectresults.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/selectresults.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/selectresults.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -42,8 +42,14 @@ </span><span class="cx"> assert self.res.count() == 100 </span><span class="cx"> assert self.res.filter(foo.c.bar<30).min(foo.c.bar) == 0 </span><span class="cx"> assert self.res.filter(foo.c.bar<30).max(foo.c.bar) == 29 </span><ins>+ + @testbase.unsupported('mysql') + def test_aggregate_1(self): </ins><span class="cx"> # this one fails in mysql as the result comes back as a string </span><span class="cx"> assert self.res.filter(foo.c.bar<30).sum(foo.c.bar) == 435 </span><ins>+ + @testbase.unsupported('postgres', 'mysql') + def test_aggregate_2(self): </ins><span class="cx"> # this one fails with postgres, the floating point comparison fails </span><span class="cx"> assert self.res.filter(foo.c.bar<30).avg(foo.c.bar) == 14.5 </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemybranchesschematesttestbasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/testbase.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/testbase.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/testbase.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -74,13 +74,44 @@ </span><span class="cx"> db = EngineAssert(db) </span><span class="cx"> metadata = sqlalchemy.BoundMetaData(db) </span><span class="cx"> </span><ins>+def unsupported(*dbs): + """a decorator that marks a test as unsupported by one or more database implementations""" + def decorate(func): + name = db.name + for d in dbs: + if d == name: + def lala(self): + echo_text("'" + func.__name__ + "' unsupported on DB implementation '" + name + "'") + lala.__name__ = func.__name__ + return lala + else: + return func + return decorate + +def supported(*dbs): + """a decorator that marks a test as supported by one or more database implementations""" + def decorate(func): + name = db.name + for d in dbs: + if d == name: + return func + else: + def lala(self): + echo_text("'" + func.__name__ + "' unsupported on DB implementation '" + name + "'") + lala.__name__ = func.__name__ + return lala + return decorate + +def echo_text(text): + print text + </ins><span class="cx"> class PersistTest(unittest.TestCase): </span><span class="cx"> """persist base class, provides default setUpAll, tearDownAll and echo functionality""" </span><span class="cx"> def __init__(self, *args, **params): </span><span class="cx"> unittest.TestCase.__init__(self, *args, **params) </span><span class="cx"> def echo(self, text): </span><span class="cx"> if echo: </span><del>- print text </del><ins>+ echo_text(text) </ins><span class="cx"> def setUpAll(self): </span><span class="cx"> pass </span><span class="cx"> def tearDownAll(self): </span></span></pre></div> <a id="sqlalchemybranchesschematesttesttypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/testtypes.py (1357 => 1358)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/testtypes.py 2006-04-29 16:42:37 UTC (rev 1357) +++ sqlalchemy/branches/schema/test/testtypes.py 2006-04-29 17:16:16 UTC (rev 1358) </span><span class="lines">@@ -2,7 +2,8 @@ </span><span class="cx"> import string,datetime, re, sys </span><span class="cx"> from testbase import PersistTest, AssertMixin </span><span class="cx"> import testbase </span><del>- </del><ins>+import sqlalchemy.engine.url as url + </ins><span class="cx"> db = testbase.db </span><span class="cx"> </span><span class="cx"> class MyType(types.TypeEngine): </span><span class="lines">@@ -14,21 +15,48 @@ </span><span class="cx"> return value + "BIND_OUT" </span><span class="cx"> def adapt(self, typeobj): </span><span class="cx"> return typeobj() </span><del>- def adapt_args(self): - return self </del><span class="cx"> </span><del>-class MyDecoratedType(types.String): </del><ins>+class MyDecoratedType(types.TypeDecorator): + impl = String </ins><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> return "BIND_IN"+ value </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return value + "BIND_OUT" </span><del>- </del><ins>+ def copy(self): + return MyDecoratedType() + </ins><span class="cx"> class MyUnicodeType(types.Unicode): </span><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> return "UNI_BIND_IN"+ value </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return value + "UNI_BIND_OUT" </span><ins>+ def copy(self): + return MyUnicodeType(self.impl.length) </ins><span class="cx"> </span><ins>+class AdaptTest(PersistTest): + def testadapt(self): + e1 = url.URL('postgres').get_module().dialect() + e2 = url.URL('mysql').get_module().dialect() + e3 = url.URL('sqlite').get_module().dialect() + + type = String(40) + + t1 = type.dialect_impl(e1) + t2 = type.dialect_impl(e2) + t3 = type.dialect_impl(e3) + assert t1 != t2 + assert t2 != t3 + assert t3 != t1 + + def testdecorator(self): + t1 = Unicode(20) + t2 = Unicode() + assert isinstance(t1.impl, String) + assert not isinstance(t1.impl, TEXT) + assert (t1.impl.length == 20) + assert isinstance(t2.impl, TEXT) + assert t2.impl.length is None + </ins><span class="cx"> class OverrideTest(PersistTest): </span><span class="cx"> """tests user-defined types, including a full type as well as a TypeDecorator""" </span><span class="cx"> </span><span class="lines">@@ -132,7 +160,15 @@ </span><span class="cx"> self.assert_(isinstance(x['plain_data'], unicode) and x['plain_data'] == unicodedata) </span><span class="cx"> finally: </span><span class="cx"> db.engine.dialect.convert_unicode = prev_unicode </span><del>- </del><ins>+ +class Foo(object): + def __init__(self, moredata): + self.data = 'im data' + self.stuff = 'im stuff' + self.moredata = moredata + def __eq__(self, other): + return other.data == self.data and other.stuff == self.stuff and other.moredata==self.moredata + </ins><span class="cx"> class BinaryTest(AssertMixin): </span><span class="cx"> def setUpAll(self): </span><span class="cx"> global binary_table </span><span class="lines">@@ -140,20 +176,28 @@ </span><span class="cx"> Column('primary_id', Integer, primary_key=True), </span><span class="cx"> Column('data', Binary), </span><span class="cx"> Column('data_slice', Binary(100)), </span><del>- Column('misc', String(30))) </del><ins>+ Column('misc', String(30)), + Column('pickled', PickleType) + ) </ins><span class="cx"> binary_table.create() </span><span class="cx"> def tearDownAll(self): </span><span class="cx"> binary_table.drop() </span><span class="cx"> def testbinary(self): </span><ins>+ testobj1 = Foo('im foo 1') + testobj2 = Foo('im foo 2') + </ins><span class="cx"> stream1 =self.get_module_stream('sqlalchemy.sql') </span><del>- stream2 =self.get_module_stream('sqlalchemy.engine') - binary_table.insert().execute(primary_id=1, misc='sql.pyc', data=stream1, data_slice=stream1[0:100]) - binary_table.insert().execute(primary_id=2, misc='engine.pyc', data=stream2, data_slice=stream2[0:99]) </del><ins>+ stream2 =self.get_module_stream('sqlalchemy.schema') + binary_table.insert().execute(primary_id=1, misc='sql.pyc', data=stream1, data_slice=stream1[0:100], pickled=testobj1) + binary_table.insert().execute(primary_id=2, misc='schema.pyc', data=stream2, data_slice=stream2[0:99], pickled=testobj2) </ins><span class="cx"> l = binary_table.select().execute().fetchall() </span><span class="cx"> print len(stream1), len(l[0]['data']), len(l[0]['data_slice']) </span><span class="cx"> self.assert_(list(stream1) == list(l[0]['data'])) </span><span class="cx"> self.assert_(list(stream1[0:100]) == list(l[0]['data_slice'])) </span><span class="cx"> self.assert_(list(stream2) == list(l[1]['data'])) </span><ins>+ self.assert_(testobj1 == l[0]['pickled']) + self.assert_(testobj2 == l[1]['pickled']) + </ins><span class="cx"> def get_module_stream(self, name): </span><span class="cx"> mod = __import__(name) </span><span class="cx"> for token in name.split('.')[1:]: </span></span></pre> </div> </div> </body> </html> |