[Sqlalchemy-commits] [1120] sqlalchemy/branches/new_types/test: overhaul to types to work in a more
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-03-09 18:22:42
|
<!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>[1120] sqlalchemy/branches/new_types/test: overhaul to types to work in a more simple fashion</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1120</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-09 12:22:32 -0600 (Thu, 09 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>overhaul to types to work in a more simple fashion</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesnew_typeslibsqlalchemytypespy">sqlalchemy/branches/new_types/lib/sqlalchemy/types.py</a></li> <li><a href="#sqlalchemybranchesnew_typestesttesttypespy">sqlalchemy/branches/new_types/test/testtypes.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesnew_typeslibsqlalchemytypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_types/lib/sqlalchemy/types.py (1119 => 1120)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_types/lib/sqlalchemy/types.py 2006-03-09 16:39:31 UTC (rev 1119) +++ sqlalchemy/branches/new_types/lib/sqlalchemy/types.py 2006-03-09 18:22:32 UTC (rev 1120) </span><span class="lines">@@ -14,52 +14,46 @@ </span><span class="cx"> import sqlalchemy.util as util </span><span class="cx"> </span><span class="cx"> class TypeEngine(object): </span><ins>+ basetypes = [] + def _get_impl(self): + if hasattr(self, '_impl'): + return self._impl + else: + return NULLTYPE + def _set_impl(self, impl): + self._impl = impl + impl = property(_get_impl, _set_impl) </ins><span class="cx"> def get_col_spec(self): </span><del>- raise NotImplementedError() </del><ins>+ return self.impl.get_col_spec() </ins><span class="cx"> def convert_bind_param(self, value, engine): </span><del>- raise NotImplementedError() </del><ins>+ return self.impl.convert_bind_param(value, engine) </ins><span class="cx"> def convert_result_value(self, value, engine): </span><del>- raise NotImplementedError() - def adapt(self, typeobj): - """given a class that is a subclass of this TypeEngine's class, produces a new - instance of that class with an equivalent state to this TypeEngine. The given - class is a database-specific subclass which is obtained via a lookup dictionary, - mapped against the class returned by the class_to_adapt() method.""" - return typeobj() </del><ins>+ return self.impl.convert_result_value(value, engine) + def set_impl(self, impltype): + self.impl = impltype(**self.get_constructor_args()) + def get_constructor_args(self): + return {} </ins><span class="cx"> def adapt_args(self): </span><del>- """Returns an instance of this TypeEngine instance's class, adapted according - to the constructor arguments of this TypeEngine. Default return value is - just this object instance.""" </del><span class="cx"> return self </span><del>- def class_to_adapt(self): - """returns the class that should be sent to the adapt() method. This class - will be used to lookup an approprate database-specific subclass.""" - return self.__class__ -# def __repr__(self): - # return util.generic_repr(self) - </del><ins>+ </ins><span class="cx"> def adapt_type(typeobj, colspecs): </span><del>- """given a generic type from this package, and a dictionary of - "conversion" specs from a DB-specific package, adapts the type - to a correctly-configured type instance from the DB-specific package.""" - if type(typeobj) is type: </del><ins>+ if isinstance(typeobj, type): </ins><span class="cx"> typeobj = typeobj() </span><del>- # if the type is not a base type, i.e. not from our module, or its Null, - # we return the type as is - if (typeobj.__module__ != 'sqlalchemy.types' or typeobj.__class__ is NullTypeEngine) and not isinstance(typeobj, TypeDecorator): - return typeobj - typeobj = typeobj.adapt_args() - t = typeobj.class_to_adapt() - for t in t.__mro__[0:-1]: </del><ins>+ t2 = typeobj.adapt_args() + for t in t2.__class__.__mro__[0:-1]: </ins><span class="cx"> try: </span><del>- return typeobj.adapt(colspecs[t]) - except KeyError, e: </del><ins>+ impltype = colspecs[t] + break + except KeyError: </ins><span class="cx"> pass </span><del>- return typeobj.adapt(typeobj.__class__) </del><ins>+ else: + # couldnt adapt...raise exception ? + return typeobj + typeobj.set_impl(impltype) + typeobj.impl.impl = NULLTYPE + return typeobj </ins><span class="cx"> </span><span class="cx"> class NullTypeEngine(TypeEngine): </span><del>- def __init__(self, *args, **kwargs): - pass </del><span class="cx"> def get_col_spec(self): </span><span class="cx"> raise NotImplementedError() </span><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="lines">@@ -68,32 +62,15 @@ </span><span class="cx"> return value </span><span class="cx"> </span><span class="cx"> class TypeDecorator(object): </span><del>- def get_col_spec(self): - return self.extended.get_col_spec() - def adapt(self, typeobj): - if self.extended is self: - t = self.__class__.__mro__[2] - self.extended = t.adapt(self, typeobj) - else: - self.extended = self.extended.adapt(typeobj) - return self - def adapt_args(self): - t = self.__class__.__mro__[2] - self.extended = t.adapt_args(self) - return self - def class_to_adapt(self): - return self.extended.__class__ </del><ins>+ """TypeDecorator is deprecated""" + pass </ins><span class="cx"> </span><del>-class String(NullTypeEngine): </del><ins>+ +class String(TypeEngine): </ins><span class="cx"> def __init__(self, length = None): </span><span class="cx"> self.length = length </span><del>- def adapt(self, typeobj): - return typeobj(self.length) - def adapt_args(self): - if self.length is None: - return TEXT() - else: - return self </del><ins>+ def get_constructor_args(self): + return {'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">@@ -104,10 +81,13 @@ </span><span class="cx"> return value </span><span class="cx"> else: </span><span class="cx"> return value.decode('utf-8') </span><del>- -class Unicode(TypeDecorator,String): - def __init__(self, length=None): - String.__init__(self, length) </del><ins>+ def adapt_args(self): + if self.length is None: + return TEXT() + else: + return self + +class Unicode(String): </ins><span class="cx"> def convert_bind_param(self, value, engine): </span><span class="cx"> if isinstance(value, unicode): </span><span class="cx"> return value.encode('utf-8') </span><span class="lines">@@ -119,49 +99,48 @@ </span><span class="cx"> else: </span><span class="cx"> return value </span><span class="cx"> </span><del>-class Integer(NullTypeEngine): </del><ins>+class Integer(TypeEngine): </ins><span class="cx"> """integer datatype""" </span><del>- # TODO: do string bind params need int(value) performed before sending ? - # seems to be not needed with SQLite, Postgres </del><span class="cx"> pass </span><del>- -class Smallinteger(Integer): </del><ins>+ +class SmallInteger(Integer): </ins><span class="cx"> """ smallint datatype """ </span><span class="cx"> pass </span><del>- -class Numeric(NullTypeEngine): </del><ins>+Smallinteger = SmallInteger + +class Numeric(TypeEngine): </ins><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 adapt(self, typeobj): - return typeobj(self.precision, self.length) </del><ins>+ def get_constructor_args(self): + return {'precision':self.precision, 'length':self.length} </ins><span class="cx"> </span><del>-class Float(NullTypeEngine): </del><ins>+class Float(TypeEngine): </ins><span class="cx"> def __init__(self, precision = 10): </span><span class="cx"> self.precision = precision </span><del>- def adapt(self, typeobj): - return typeobj(self.precision) </del><ins>+ def get_constructor_args(self): + return {'precision':self.precision} </ins><span class="cx"> </span><del>-class DateTime(NullTypeEngine): </del><ins>+class DateTime(TypeEngine): </ins><span class="cx"> pass </span><span class="cx"> </span><del>-class Date(NullTypeEngine): </del><ins>+class Date(TypeEngine): </ins><span class="cx"> pass </span><span class="cx"> </span><del>-class Time(NullTypeEngine): </del><ins>+class Time(TypeEngine): </ins><span class="cx"> pass </span><span class="cx"> </span><del>-class Binary(NullTypeEngine): </del><ins>+class Binary(TypeEngine): </ins><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, engine): </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 adapt(self, typeobj): - return typeobj(self.length) </del><ins>+ def get_constructor_args(self): + return {'length':self.length} </ins><span class="cx"> </span><del>-class Boolean(NullTypeEngine): </del><ins>+class Boolean(TypeEngine): </ins><span class="cx"> pass </span><span class="cx"> </span><span class="cx"> class FLOAT(Float):pass </span></span></pre></div> <a id="sqlalchemybranchesnew_typestesttesttypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/new_types/test/testtypes.py (1119 => 1120)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/new_types/test/testtypes.py 2006-03-09 16:39:31 UTC (rev 1119) +++ sqlalchemy/branches/new_types/test/testtypes.py 2006-03-09 18:22:32 UTC (rev 1120) </span><span class="lines">@@ -23,19 +23,25 @@ </span><span class="cx"> def convert_result_value(self, value, engine): </span><span class="cx"> return value + "BIND_OUT" </span><span class="cx"> </span><ins>+class MyUnicodeType(types.Unicode): + def convert_bind_param(self, value, engine): + return "UNI_BIND_IN"+ value + def convert_result_value(self, value, engine): + return value + "UNI_BIND_OUT" + </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="cx"> def testprocessing(self): </span><span class="cx"> </span><span class="cx"> global users </span><del>- users.insert().execute(user_id = 2, goofy = 'jack', goofy2='jack', goofy3='jack') - users.insert().execute(user_id = 3, goofy = 'lala', goofy2='lala', goofy3='lala') - users.insert().execute(user_id = 4, goofy = 'fred', goofy2='fred', goofy3='fred') </del><ins>+ users.insert().execute(user_id = 2, goofy = 'jack', goofy2='jack', goofy3='jack', goofy4='jack') + users.insert().execute(user_id = 3, goofy = 'lala', goofy2='lala', goofy3='lala', goofy4='lala') + users.insert().execute(user_id = 4, goofy = 'fred', goofy2='fred', goofy3='fred', goofy4='fred') </ins><span class="cx"> </span><span class="cx"> l = users.select().execute().fetchall() </span><span class="cx"> print repr(l) </span><del>- self.assert_(l == [(2, 'BIND_INjackBIND_OUT', 'BIND_INjackBIND_OUT', 'BIND_INjackBIND_OUT'), (3, 'BIND_INlalaBIND_OUT', 'BIND_INlalaBIND_OUT', 'BIND_INlalaBIND_OUT'), (4, 'BIND_INfredBIND_OUT', 'BIND_INfredBIND_OUT', 'BIND_INfredBIND_OUT')]) </del><ins>+ self.assert_(l == [(2, 'BIND_INjackBIND_OUT', 'BIND_INjackBIND_OUT', 'BIND_INjackBIND_OUT', u'UNI_BIND_INjackUNI_BIND_OUT'), (3, 'BIND_INlalaBIND_OUT', 'BIND_INlalaBIND_OUT', 'BIND_INlalaBIND_OUT', u'UNI_BIND_INlalaUNI_BIND_OUT'), (4, 'BIND_INfredBIND_OUT', 'BIND_INfredBIND_OUT', 'BIND_INfredBIND_OUT', u'UNI_BIND_INfredUNI_BIND_OUT')]) </ins><span class="cx"> </span><span class="cx"> def setUpAll(self): </span><span class="cx"> global users </span><span class="lines">@@ -49,6 +55,9 @@ </span><span class="cx"> </span><span class="cx"> # decorated type without an argument, it will adapt_args to TEXT </span><span class="cx"> Column('goofy3', MyDecoratedType, nullable = False), </span><ins>+ + Column('goofy4', MyUnicodeType, nullable = False), + </ins><span class="cx"> ) </span><span class="cx"> </span><span class="cx"> users.create() </span></span></pre> </div> </div> </body> </html> |