On Mon, Oct 11, 2010 at 06:17:02PM +0200, Georges Schutz wrote:
> import sqlobject as sobj
> 
> class Person(sobj.SQLObject):
>      name = sobj.StringCol(default=None)
> 
> conn = sobj.connectionForURI('sqlite:/:memory:')
> 
> Person.createTable(ifNotExists=True, connection=conn)
> Person(name="P. Dummy", connection=conn)
> 
> p = Person.selectBy(name = "P. Dummy", connection=conn)
...
>    File 
> "C:\Python26\lib\site-packages\sqlobject-0.14.0-py2.6.egg\sqlobject\dbconnection.py",
>  
> line 850, in getConnection
>      "No connection has been defined for this thread "
> AttributeError: No connection has been defined for this thread or process

   Congratulations, you managed to find quite a subtle problem! Sometimes
validators need additional information from connection - most often
validators need encoding (charset) to convert between str and unicode. In
your example there is no per-class connection, and validators don't get a
connection at all. In many cases it could be fixed - the attached patch is
for testing and discussing.
   The problem is rather old but it manifested itself now because in
version 0.13 I refactored validators' code.

> conn = sobj.connectionForURI('sqlite:/:memory:')
>                                       ^^^^^^^^
> Person.createTable(ifNotExists=True, connection=conn)
                     ^^^^^^^^^^^^^^^^
   I seems you prepared memory to be rather persistent! (Just kidding.)

Oleg.
-- 
     Oleg Broytman            http://phd.pp.ru/            p...@phd.pp.ru
           Programmers don't die, they just GOSUB without RETURN.
Index: sqlbuilder.py
===================================================================
--- sqlbuilder.py	(revision 4248)
+++ sqlbuilder.py	(working copy)
@@ -80,8 +80,9 @@
 
 
 class SQLObjectState(object):
-    def __init__(self, soObject):
+    def __init__(self, soObject, connection=None):
         self.soObject = weakref.proxy(soObject)
+        self.connection = connection
 
 
 safeSQLRE = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_\.]*$')
Index: main.py
===================================================================
--- main.py	(revision 4248)
+++ main.py	(working copy)
@@ -1318,7 +1318,7 @@
         for n, v in zip(name, value):
             from_python = getattr(cls, '_SO_from_python_' + n)
             if from_python:
-                v = from_python(v, sqlbuilder.SQLObjectState(cls))
+                v = from_python(v, sqlbuilder.SQLObjectState(cls, connection=connection))
             new_value.append(v)
         condition = sqlbuilder.AND(*[getattr(cls.q, n)==v for n,v in zip(name, new_value)])
         return (connection or cls._connection)._SO_selectOneAlt(
Index: dbconnection.py
===================================================================
--- dbconnection.py	(revision 4248)
+++ dbconnection.py	(working copy)
@@ -582,7 +582,7 @@
             if key in kw:
                 value = kw.pop(key)
                 if col.from_python:
-                    value = col.from_python(value, sqlbuilder.SQLObjectState(soClass))
+                    value = col.from_python(value, sqlbuilder.SQLObjectState(soClass, connection=self))
                 data[col.dbName] = value
             elif col.foreignName in kw:
                 obj = kw.pop(col.foreignName)
Index: col.py
===================================================================
--- col.py	(revision 4248)
+++ col.py	(working copy)
@@ -498,13 +498,19 @@
     def to_python(self, value, state):
         if value is None:
             return None
-        connection = state.soObject._connection
-        dbEncoding = getattr(connection, "dbEncoding", None) or "ascii"
+        try:
+            connection = state.connection or state.soObject._connection
+        except AttributeError:
+            dbEncoding = "ascii"
+            binaryType = type(None) # Just a simple workaround
+        else:
+            dbEncoding = getattr(connection, "dbEncoding", None) or "ascii"
+            binaryType = connection._binaryType
         if isinstance(value, unicode):
             return value.encode(dbEncoding)
         if self.dataType and isinstance(value, self.dataType):
             return value
-        if isinstance(value, (str, buffer, connection._binaryType, sqlbuilder.SQLExpression)):
+        if isinstance(value, (str, buffer, binaryType, sqlbuilder.SQLExpression)):
             return value
         if hasattr(value, '__unicode__'):
             return unicode(value).encode(dbEncoding)
@@ -1300,10 +1306,14 @@
             return value
         if isinstance(value, float):
             value = str(value)
-        connection = state.soObject._connection
-        if hasattr(connection, "decimalSeparator"):
-            value = value.replace(connection.decimalSeparator, ".")
         try:
+            connection = state.connection or state.soObject._connection
+        except AttributeError:
+            pass
+        else:
+            if hasattr(connection, "decimalSeparator"):
+                value = value.replace(connection.decimalSeparator, ".")
+        try:
             return Decimal(value)
         except:
             raise validators.Invalid("expected a Decimal in the DecimalCol '%s', got %s %r instead" % \
@@ -1315,10 +1325,14 @@
         if isinstance(value, float):
             value = str(value)
         if isinstance(value, basestring):
-            connection = state.soObject._connection
-            if hasattr(connection, "decimalSeparator"):
-                value = value.replace(connection.decimalSeparator, ".")
             try:
+                connection = state.connection or state.soObject._connection
+            except AttributeError:
+                pass
+            else:
+                if hasattr(connection, "decimalSeparator"):
+                    value = value.replace(connection.decimalSeparator, ".")
+            try:
                 return Decimal(value)
             except:
                 raise validators.Invalid("can not parse Decimal value '%s' in the DecimalCol from '%s'" %
@@ -1422,12 +1436,19 @@
     def to_python(self, value, state):
         if value is None:
             return None
+        try:
+            connection = state.connection or state.soObject._connection
+        except AttributeError:
+            dbName = None
+            binaryType = type(None) # Just a simple workaround
+        else:
+            dbName = connection.dbName
+            binaryType = connection._binaryType
         if isinstance(value, str):
-            connection = state.soObject._connection
-            if connection.dbName == "sqlite":
+            if dbName == "sqlite":
                 value = connection.module.decode(value)
             return value
-        if isinstance(value, (buffer, state.soObject._connection._binaryType)):
+        if isinstance(value, (buffer, binaryType)):
             cachedValue = self._cachedValue
             if cachedValue and cachedValue[1] == value:
                 return cachedValue[0]
@@ -1440,7 +1461,8 @@
     def from_python(self, value, state):
         if value is None:
             return None
-        binary = state.soObject._connection.createBinary(value)
+        connection = state.connection or state.soObject._connection
+        binary = connection.createBinary(value)
         self._cachedValue = (value, binary)
         return binary
 
@@ -1492,8 +1514,12 @@
         if value is None:
             return None
         if isinstance(value, unicode):
-            connection = state.soObject._connection
-            dbEncoding = getattr(connection, "dbEncoding", None) or "ascii"
+            try:
+                connection = state.connection or state.soObject._connection
+            except AttributeError:
+                dbEncoding = "ascii"
+            else:
+                dbEncoding = getattr(connection, "dbEncoding", None) or "ascii"
             value = value.encode(dbEncoding)
         if isinstance(value, str):
             return pickle.loads(value)
------------------------------------------------------------------------------
Beautiful is writing same markup. Internet Explorer 9 supports
standards for HTML5, CSS3, SVG 1.1,  ECMAScript5, and DOM L2 & L3.
Spend less time writing and  rewriting code and more time creating great
experiences on the web. Be a part of the beta today.
http://p.sf.net/sfu/beautyoftheweb
_______________________________________________
sqlobject-discuss mailing list
sqlobject-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss

Reply via email to