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