dabo Commit
Revision 2588
Date: 2006-12-30 14:53:24 -0800 (Sat, 30 Dec 2006)
Author: Paul
Changed:
U branches/paul_sandbox/dabo/biz/dBizobj.py
U branches/paul_sandbox/dabo/db/dCursorMixin.py
Log:
I've worked a bit on the new memento design while on vacation here in
Miami Beach, and things seem to be coming together nicely. Of course,
with all big changes I keep finding other places to clean up, and I
can't remember everything but when/if this gets merged back into
trunk I'll be more specific about the changes.
Diff:
Modified: branches/paul_sandbox/dabo/biz/dBizobj.py
===================================================================
--- branches/paul_sandbox/dabo/biz/dBizobj.py 2006-12-30 18:02:17 UTC (rev
2587)
+++ branches/paul_sandbox/dabo/biz/dBizobj.py 2006-12-30 22:53:24 UTC (rev
2588)
@@ -6,8 +6,8 @@
from dabo.dLocalize import _
import dabo.dException as dException
from dabo.dObject import dObject
+from dabo.lib.profilehooks import profile as profile
-
class dBizobj(dObject):
""" The middle tier, where the business logic resides."""
# Class to instantiate for the cursor object
@@ -253,48 +253,55 @@
def saveAll(self, startTransaction=False, topLevel=True):
- """ Iterates through all the records of the bizobj, and calls
save()
- for any record that has pending changes.
- """
- changedRows = self.getChangedRows()
- cursor = self._CurrentCursor
+ """Saves all changes to the bizobj and children."""
useTransact = startTransaction or topLevel
- if useTransact:
- # Tell the cursor to begin a transaction, if needed.
- cursor.beginTransaction()
- try:
- self.scanRows(self.save, changedRows,
startTransaction=False, topLevel=False)
- except dException.ConnectionLostException, e:
- raise dException.ConnectionLostException, e
- except dException.DBQueryException, e:
- # Something failed; reset things.
+ old_currentCursorKey = self.__currentCursorKey
+ old_pk = getattr(self.Record, self.KeyField)
+
+ for key, cursor in self.__cursors.iteritems():
if useTransact:
- cursor.rollbackTransaction()
- # Pass the exception to the UI
- raise dException.DBQueryException, e
- except dException.dException, e:
+ # Tell the cursor to begin a transaction, if
needed.
+ cursor.beginTransaction()
+# self.scanRows(self.save, changedRows,
startTransaction=False, topLevel=False)
+ print "saveAll: key, cursor:", key, cursor
+ self._CurrentCursor = key
+ changed_keys = list(set(cursor._mementos.keys() +
cursor._newRecords.keys()))
+ for pk in changed_keys:
+ print "changed_key:", pk
+ self._moveToPK(pk)
+ try:
+ self.save(startTransaction=False,
topLevel=False)
+ except dException.ConnectionLostException, e:
+ self._CurrentCursor =
old_currentCursorKey
+ self._moveToPK(old_pk)
+ raise
dException.ConnectionLostException, e
+ except dException.DBQueryException, e:
+ # Something failed; reset things.
+ if useTransact:
+ cursor.rollbackTransaction()
+ # Pass the exception to the UI
+ self._CurrentCursor =
old_currentCursorKey
+ self._moveToPK(old_pk)
+ raise dException.DBQueryException, e
+ except dException.dException, e:
+ if useTransact:
+ cursor.rollbackTransaction()
+ self._CurrentCursor =
old_currentCursorKey
+ self._moveToPK(old_pk)
+ raise
+
if useTransact:
- cursor.rollbackTransaction()
- raise dException.dException, e
+ cursor.commitTransaction()
- if useTransact:
- cursor.commitTransaction()
+ self._CurrentCursor = old_currentCursorKey
+ self._moveToPK(old_pk)
- def _saveRowIfChanged(self, startTransaction, topLevel):
- """ Meant to be called as part of a scan loop. That means that
we can
- assume that the current record is the one we want to act on.
Also, we
- can pass False for the two parameters, since they will have
already been
- accounted for in the calling method.
- """
- if self.isChanged():
- self.save(startTransaction, topLevel)
+ def save(self, startTransaction=False, topLevel=True):
+ """Save any changes that have been made in the current row.
-
- def save(self, startTransaction=False, topLevel=True):
- """ Save any changes that have been made in the data set. If the
- save is successful, the save() of all child bizobjs will be
+ If the save is successful, the saveAll() of all child bizobjs
will be
called as well.
"""
cursor = self._CurrentCursor
@@ -356,7 +363,7 @@
if useTransact:
cursor.rollbackTransaction()
# Pass the exception to the UI
- raise dException.dException, e
+ raise
# Some backends (Firebird particularly) need to be told to write
# their changes even if no explicit transaction was started.
@@ -369,38 +376,31 @@
def cancelAll(self):
- """ Iterates through all the records, canceling each in turn.
"""
- errMsg = self.beforeCancel()
- if errMsg:
- raise dException.dException, errMsg
- for cursor in self.__cursors.values():
- cursor.cancel(allRows=True)
- for child in self.__children:
- child.cancelAll()
- self.afterCancel()
+ """Cancel all changes made to the current dataset, including
all children."""
+ self.scanChangedRows(self.cancel, allCursors=True)
def cancel(self):
- """ Cancel any changes to the current record, reverting the
fields
- back to their original values.
+ """Cancel all changes to the current record and all children.
+
+ Two hook methods will be called: beforeCancel() and
afterCancel(). The
+ former, if it returns an error message, will raise an exception
and not
+ continue cancelling the record.
"""
errMsg = self.beforeCancel()
if errMsg:
raise dException.dException, errMsg
- # Tell the cursor to cancel any changes
+ # Tell the cursor and all children to cancel themselves:
self._CurrentCursor.cancel()
- # Tell each child to cancel themselves
for child in self.__children:
child.cancelAll()
- #child.requery()
-# self.setMemento()
self.afterCancel()
def delete(self, startTransaction=False):
- """ Delete the current row of the data set."""
+ """Delete the current row of the data set."""
cursor = self._CurrentCursor
errMsg = self.beforeDelete()
if not errMsg:
@@ -557,6 +557,43 @@
self.RowNumber = row
+ def scanChangedRows(self, func, allCursors=False, *args, **kwargs):
+ """Move the record pointer to each changed row, and call func.
+
+ If allCursors is True, all other cursors for different parent
records will
+ be iterated as well.
+
+ If you want to end the scan on the next iteration, set
self.exitScan=True.
+
+ Records are scanned in arbitrary order. Any exception raised by
calling
+ func() will be passed up to the caller.
+ """
+ self.exitScan = False
+ old_currentCursorKey = self.__currentCursorKey
+ old_pk = getattr(self.Record, self.KeyField)
+
+ if allCursors:
+ cursors = self.__cursors
+ else:
+ cursors = [{None: self._CurrentCursor}]
+
+ for key, cursor in cursors.iteritems():
+ self._CurrentCursor = key
+ changed_keys = list(set(cursor._mementos.keys() +
cursor._newRecords.keys()))
+ for pk in changed_keys:
+ self._moveToPK(pk)
+ try:
+ func(*args, **kwargs)
+ except:
+ # Reset things and bail:
+ self._CurrentCursor =
old_currentCursorKey
+ self._moveToPK(old_pk)
+ raise
+
+ self._CurrentCursor = old_currentCursorKey
+ self._moveToPK(old_pk)
+
+
def getFieldNames(self):
"""Returns a tuple of all the field names in the cursor."""
flds = self._CurrentCursor.getFields()
@@ -845,6 +882,7 @@
return ret
+ @profile
def isAnyChanged(self):
""" Returns True if any record in the current record set has
been
changed.
@@ -939,6 +977,13 @@
# Fill in the link to the parent record
if self.Parent and self.FillLinkFromParent and self.LinkField:
self.setParentFK()
+
+ # Add the new record flag if there's a KeyField defined:
+ if self.KeyField:
+ rec = self._CurrentCursor._records[self.RowNumber]
+ print "dbizobj.new(): pk: ", rec[self.KeyField]
+ self._CurrentCursor._newRecords[rec[self.KeyField]] =
None
+
# Call the custom hook method
self.onNew()
Modified: branches/paul_sandbox/dabo/db/dCursorMixin.py
===================================================================
--- branches/paul_sandbox/dabo/db/dCursorMixin.py 2006-12-30 18:02:17 UTC
(rev 2587)
+++ branches/paul_sandbox/dabo/db/dCursorMixin.py 2006-12-30 22:53:24 UTC
(rev 2588)
@@ -831,11 +831,8 @@
row = self.RowNumber
rec = self._records[row]
- mem = self._mementos[rec[self.KeyField]]
+ mem = self._mementos.get(rec[self.KeyField], {})
- print "mementos:", self._mementos
- print "mem", mem
-
for k, v in mem.items():
ret[k] = (v, rec[k])
return ret
@@ -972,7 +969,7 @@
# this object started the transaction.
if useTransaction:
self.rollbackTransaction()
- raise dException.QueryException, e
+ raise
if useTransaction:
self.beginTransaction()
@@ -1169,9 +1166,7 @@
def delete(self, delRowNum=None):
- """ Delete the specified row. If no row specified,
- delete the currently active row.
- """
+ """Delete the specified row, or the currently active row."""
if self.RowNumber < 0 or self.RowCount == 0:
# No query has been run yet
raise dException.NoRecordsException, _("No record to
delete")
@@ -1180,10 +1175,12 @@
delRowNum = self.RowNumber
rec = self._records[delRowNum]
- newrec = rec.has_key(kons.CURSOR_NEWFLAG)
- if newrec:
+# newrec = rec.has_key(kons.CURSOR_NEWFLAG)
+ if self._newRecords.has_key(rec[self.KeyField]):
+ print "delete(): new record"
res = True
else:
+ print "delete(): not new record", self._newRecords
pkWhere = self.makePkWhere()
# some backends(PostgreSQL) don't return information
about number of deleted rows
# try to fetch it before
@@ -1925,9 +1922,10 @@
def _getIsAdding(self):
""" Return True if the current record is a new record."""
- return
self._records[self.RowNumber].has_key(kons.CURSOR_NEWFLAG)
-
+# return
self._records[self.RowNumber].has_key(kons.CURSOR_NEWFLAG)
+ return
self._newRecords.has_key(self._records[self.RowNumber][self.KeyField])
+
def _getKeyField(self):
try:
return self._keyField
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev