[Sqlalchemy-commits] [1356] sqlalchemy/trunk/test: more work on types.
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-29 16:12:15
|
<!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>[1356] sqlalchemy/trunk/test: more work on types.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1356</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-29 11:12:02 -0500 (Sat, 29 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>more work on types. this is the simplest implementation which is a little more manual</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemytypespy">sqlalchemy/trunk/lib/sqlalchemy/types.py</a></li> <li><a href="#sqlalchemytrunktesttesttypespy">sqlalchemy/trunk/test/testtypes.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemytypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/types.py (1355 => 1356)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/types.py 2006-04-29 01:05:13 UTC (rev 1355) +++ sqlalchemy/trunk/lib/sqlalchemy/types.py 2006-04-29 16:12:02 UTC (rev 1356) </span><span class="lines">@@ -12,6 +12,7 @@ </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="lines">@@ -25,11 +26,7 @@ </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><del>- def get_constructor_args(self): - return {} - def adapt_args(self): - return self - </del><ins>+ </ins><span class="cx"> class TypeEngine(AbstractType): </span><span class="cx"> def __init__(self, *args, **params): </span><span class="cx"> pass </span><span class="lines">@@ -44,16 +41,22 @@ </span><span class="cx"> return value </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return value </span><ins>+ def adapt(self, cls): + return cls() </ins><span class="cx"> </span><ins>+AbstractType.impl = TypeEngine + </ins><span class="cx"> class TypeDecorator(AbstractType): </span><del>- def __init__(self, *args, **params): - pass </del><ins>+ def __init__(self, *args, **kwargs): + self.impl = self.__class__.impl(*args, **kwargs) </ins><span class="cx"> def engine_impl(self, engine): </span><span class="cx"> try: </span><span class="cx"> return self.impl_dict[engine] </span><span class="cx"> except: </span><span class="cx"> typedesc = engine.type_descriptor(self.impl) </span><del>- tt = self.__class__(**self.get_constructor_args()) </del><ins>+ 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__)) </ins><span class="cx"> tt.impl = typedesc </span><span class="cx"> self.impl_dict[engine] = tt </span><span class="cx"> return tt </span><span class="lines">@@ -63,6 +66,8 @@ </span><span class="cx"> return self.impl.convert_bind_param(value, engine) </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return self.impl.convert_result_value(value, engine) </span><ins>+ def copy(self): + raise NotImplementedError() </ins><span class="cx"> </span><span class="cx"> def to_instance(typeobj): </span><span class="cx"> if typeobj is None: </span><span class="lines">@@ -74,8 +79,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">@@ -84,7 +88,7 @@ </span><span class="cx"> else: </span><span class="cx"> # couldnt adapt...raise exception ? </span><span class="cx"> return typeobj </span><del>- return impltype(**t2.get_constructor_args()) </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">@@ -96,10 +100,15 @@ </span><span class="cx"> </span><span class="cx"> </span><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, engine): </span><span class="cx"> if not engine.convert_unicode or value is None or not isinstance(value, unicode): </span><span class="cx"> return value </span><span class="lines">@@ -110,11 +119,6 @@ </span><span class="cx"> return value </span><span class="cx"> else: </span><span class="cx"> return value.decode(engine.encoding) </span><del>- def adapt_args(self): - if self.length is None: - return TEXT() - else: - return self </del><span class="cx"> </span><span class="cx"> class Unicode(TypeDecorator): </span><span class="cx"> impl = String </span><span class="lines">@@ -128,7 +132,9 @@ </span><span class="cx"> return value.decode(engine.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">@@ -142,22 +148,25 @@ </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="lines">@@ -167,25 +176,26 @@ </span><span class="cx"> return engine.dbapi().Binary(value) </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return value </span><del>- def get_constructor_args(self): - return {'length':self.length} </del><ins>+ def adap(self, impltype): + return impltype(length=self.length) </ins><span class="cx"> </span><span class="cx"> class PickleType(TypeDecorator): </span><del>- def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): - """allows the pickle protocol to be specified""" - self.protocol = protocol - self.impl = Binary() - def convert_result_value(self, value, engine): - if value is None: - return None - buf = self.impl.convert_result_value(value, engine) - return pickle.loads(str(buf)) - def convert_bind_param(self, value, engine): - if value is None: - return None - return self.impl.convert_bind_param(pickle.dumps(value, self.protocol), engine) - def get_constructor_args(self): - return {} </del><ins>+ 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, engine): + if value is None: + return None + buf = self.impl.convert_result_value(value, engine) + return pickle.loads(str(buf)) + def convert_bind_param(self, value, engine): + if value is None: + return None + return self.impl.convert_bind_param(pickle.dumps(value, self.protocol), engine) + 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="sqlalchemytrunktesttesttypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/testtypes.py (1355 => 1356)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/testtypes.py 2006-04-29 01:05:13 UTC (rev 1355) +++ sqlalchemy/trunk/test/testtypes.py 2006-04-29 16:12:02 UTC (rev 1356) </span><span class="lines">@@ -14,8 +14,6 @@ </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><span class="cx"> class MyDecoratedType(types.TypeDecorator): </span><span class="cx"> impl = String </span><span class="lines">@@ -23,12 +21,16 @@ </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><span class="cx"> class AdaptTest(PersistTest): </span><span class="cx"> def testadapt(self): </span><span class="lines">@@ -44,6 +46,15 @@ </span><span class="cx"> assert t1 != t2 </span><span class="cx"> assert t2 != t3 </span><span class="cx"> assert t3 != t1 </span><ins>+ + 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"> </span><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></pre> </div> </div> </body> </html> |