Author: phd
Date: 2010-02-08 11:12:07 -0700 (Mon, 08 Feb 2010)
New Revision: 4103
Modified:
SQLObject/trunk/docs/News.txt
SQLObject/trunk/sqlobject/inheritance/__init__.py
SQLObject/trunk/sqlobject/inheritance/tests/test_deep_inheritance.py
Log:
Merged a bugfix in inheritance from revision 4102 from branch 0.12.
Modified: SQLObject/trunk/docs/News.txt
===================================================================
--- SQLObject/trunk/docs/News.txt 2010-02-08 18:10:24 UTC (rev 4102)
+++ SQLObject/trunk/docs/News.txt 2010-02-08 18:12:07 UTC (rev 4103)
@@ -26,6 +26,11 @@
the case of inherited idName inherited value takes precedence; to allow
Style to set idName reset inherited idName to None.
+SQLObject 0.12.2
+================
+
+* A bugfix ported from `SQLObject 0.11.4`_.
+
SQLObject 0.12.1
================
@@ -85,6 +90,13 @@
* Removed the last remained string exceptions.
+SQLObject 0.11.4
+================
+
+* Fixed a bug in inheritance - if creation of the row failed and if the
+ connection is not a transaction and is in autocommit mode - remove
+ parent row(s).
+
SQLObject 0.11.3
================
Modified: SQLObject/trunk/sqlobject/inheritance/__init__.py
===================================================================
--- SQLObject/trunk/sqlobject/inheritance/__init__.py 2010-02-08 18:10:24 UTC (rev 4102)
+++ SQLObject/trunk/sqlobject/inheritance/__init__.py 2010-02-08 18:12:07 UTC (rev 4103)
@@ -1,9 +1,10 @@
+from sqlobject import dbconnection
+from sqlobject import classregistry
+from sqlobject import events
from sqlobject import sqlbuilder
-from sqlobject import classregistry
from sqlobject.col import StringCol, ForeignKey
from sqlobject.main import sqlmeta, SQLObject, SelectResults, \
makeProperties, unmakeProperties, getterName, setterName
-from sqlobject import events
import iteration
def tablesUsedSet(obj, db):
@@ -109,7 +110,7 @@
def setfunc(self, val):
if not self.sqlmeta._creating and not getattr(self.sqlmeta, "row_update_sig_suppress", False):
self.sqlmeta.send(events.RowUpdateSignal, self, {cname : val})
-
+
result = setattr(self._parent, cname, val)
return setfunc
@@ -384,7 +385,20 @@
id = self._parent.id
- super(InheritableSQLObject, self)._create(id, **kw)
+ # TC: Create this record and catch all exceptions in order to destroy
+ # TC: the parent if the child can not be created.
+ try:
+ super(InheritableSQLObject, self)._create(id, **kw)
+ except:
+ # If we are outside a transaction and this is a child, destroy the parent
+ connection = self._connection
+ if (not isinstance(connection, dbconnection.Transaction) and
+ connection.autoCommit) and self.sqlmeta.parentClass:
+ self._parent.destroySelf()
+ #TC: Do we need to do this??
+ self._parent = None
+ # TC: Reraise the original exception
+ raise
def _findAlternateID(cls, name, dbName, value, connection=None):
result = list(cls.selectBy(connection, **{name: value}))
Modified: SQLObject/trunk/sqlobject/inheritance/tests/test_deep_inheritance.py
===================================================================
--- SQLObject/trunk/sqlobject/inheritance/tests/test_deep_inheritance.py 2010-02-08 18:10:24 UTC (rev 4102)
+++ SQLObject/trunk/sqlobject/inheritance/tests/test_deep_inheritance.py 2010-02-08 18:12:07 UTC (rev 4103)
@@ -13,27 +13,54 @@
manager = ForeignKey("DIManager", default=None)
class DIEmployee(DIPerson):
- position = StringCol()
+ position = StringCol(unique=True)
class DIManager(DIEmployee):
subdudes = MultipleJoin("DIPerson", joinColumn="manager_id")
def test_creation_fail():
"""
- Try to creae an Manager without specifying a position.
- this should fail without leaving any partial records in
+ Try to create a Manager without specifying a position.
+ This should fail without leaving any partial records in
the database.
"""
setupClass([DIManager, DIEmployee, DIPerson])
- kwargs ={'firstName':'John', 'lastname':'Doe'}
+ kwargs ={'firstName': 'John', 'lastname': 'Doe'}
raises(TypeError, DIManager, **kwargs)
- #what we really need to check for is partial records in the database.
- #the following is not really adaquate.
persons = DIEmployee.select(DIPerson.q.firstName == 'John')
assert persons.count() == 0
+def test_creation_fail2():
+ """
+ Try to create two Managers with the same position.
+ This should fail without leaving any partial records in
+ the database.
+
+ """
+ setupClass([DIManager, DIEmployee, DIPerson])
+
+ kwargs ={'firstName': 'John', 'lastName': 'Doe', 'position': 'Project Manager'}
+ DIManager(**kwargs)
+ persons = DIEmployee.select(DIPerson.q.firstName == 'John')
+ assert persons.count() == 1
+
+ kwargs ={'firstName': 'John', 'lastName': 'Doe II', 'position': 'Project Manager'}
+ raises(Exception, DIManager, **kwargs)
+ persons = DIPerson.select(DIPerson.q.firstName == 'John')
+ assert persons.count() == 1
+
+ if not supports('transactions'):
+ return
+ transaction = DIPerson._connection.transaction()
+ kwargs ={'firstName': 'John', 'lastName': 'Doe III', 'position': 'Project Manager'}
+ raises(Exception, DIManager, connection=transaction, **kwargs)
+ transaction.rollback()
+ transaction.begin()
+ persons = DIPerson.select(DIPerson.q.firstName == 'John', connection=transaction)
+ assert persons.count() == 1
+
def test_deep_inheritance():
setupClass([DIManager, DIEmployee, DIPerson])
|