summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/types.py143
1 files changed, 62 insertions, 81 deletions
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py
index fcd416398..f8b2b490f 100644
--- a/lib/sqlalchemy/types.py
+++ b/lib/sqlalchemy/types.py
@@ -14,52 +14,48 @@ __all__ = [ 'TypeEngine', 'TypeDecorator', 'NullTypeEngine',
import sqlalchemy.util as util
class TypeEngine(object):
+ basetypes = []
+ def __init__(self, *args, **kwargs):
+ pass
+ 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)
def get_col_spec(self):
- raise NotImplementedError()
+ return self.impl.get_col_spec()
def convert_bind_param(self, value, engine):
- raise NotImplementedError()
+ return self.impl.convert_bind_param(value, engine)
def convert_result_value(self, value, engine):
- 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()
+ 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 {}
def adapt_args(self):
- """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."""
return self
- 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)
-
+
def adapt_type(typeobj, colspecs):
- """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:
+ if isinstance(typeobj, type):
typeobj = typeobj()
- # 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]:
+ t2 = typeobj.adapt_args()
+ for t in t2.__class__.__mro__[0:-1]:
try:
- return typeobj.adapt(colspecs[t])
- except KeyError, e:
+ impltype = colspecs[t]
+ break
+ except KeyError:
pass
- return typeobj.adapt(typeobj.__class__)
+ else:
+ # couldnt adapt...raise exception ?
+ return typeobj
+ typeobj.set_impl(impltype)
+ typeobj.impl.impl = NULLTYPE
+ return typeobj
class NullTypeEngine(TypeEngine):
- def __init__(self, *args, **kwargs):
- pass
def get_col_spec(self):
raise NotImplementedError()
def convert_bind_param(self, value, engine):
@@ -68,32 +64,15 @@ class NullTypeEngine(TypeEngine):
return value
class TypeDecorator(object):
- 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__
+ """TypeDecorator is deprecated"""
+ pass
-class String(NullTypeEngine):
+
+class String(TypeEngine):
def __init__(self, length = None):
self.length = length
- def adapt(self, typeobj):
- return typeobj(self.length)
- def adapt_args(self):
- if self.length is None:
- return TEXT()
- else:
- return self
+ def get_constructor_args(self):
+ return {'length':self.length}
def convert_bind_param(self, value, engine):
if not engine.convert_unicode or value is None or not isinstance(value, unicode):
return value
@@ -104,10 +83,13 @@ class String(NullTypeEngine):
return value
else:
return value.decode('utf-8')
-
-class Unicode(TypeDecorator,String):
- def __init__(self, length=None):
- String.__init__(self, length)
+ def adapt_args(self):
+ if self.length is None:
+ return TEXT()
+ else:
+ return self
+
+class Unicode(String):
def convert_bind_param(self, value, engine):
if isinstance(value, unicode):
return value.encode('utf-8')
@@ -119,49 +101,48 @@ class Unicode(TypeDecorator,String):
else:
return value
-class Integer(NullTypeEngine):
+class Integer(TypeEngine):
"""integer datatype"""
- # TODO: do string bind params need int(value) performed before sending ?
- # seems to be not needed with SQLite, Postgres
pass
-
-class Smallinteger(Integer):
+
+class SmallInteger(Integer):
""" smallint datatype """
pass
-
-class Numeric(NullTypeEngine):
+Smallinteger = SmallInteger
+
+class Numeric(TypeEngine):
def __init__(self, precision = 10, length = 2):
self.precision = precision
self.length = length
- def adapt(self, typeobj):
- return typeobj(self.precision, self.length)
+ def get_constructor_args(self):
+ return {'precision':self.precision, 'length':self.length}
-class Float(NullTypeEngine):
+class Float(TypeEngine):
def __init__(self, precision = 10):
self.precision = precision
- def adapt(self, typeobj):
- return typeobj(self.precision)
+ def get_constructor_args(self):
+ return {'precision':self.precision}
-class DateTime(NullTypeEngine):
+class DateTime(TypeEngine):
pass
-class Date(NullTypeEngine):
+class Date(TypeEngine):
pass
-class Time(NullTypeEngine):
+class Time(TypeEngine):
pass
-class Binary(NullTypeEngine):
+class Binary(TypeEngine):
def __init__(self, length=None):
self.length = length
def convert_bind_param(self, value, engine):
return engine.dbapi().Binary(value)
def convert_result_value(self, value, engine):
return value
- def adapt(self, typeobj):
- return typeobj(self.length)
+ def get_constructor_args(self):
+ return {'length':self.length}
-class Boolean(NullTypeEngine):
+class Boolean(TypeEngine):
pass
class FLOAT(Float):pass