]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- more rearrangements of unit-of-work commit scheme to better allow
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 7 Sep 2006 20:04:10 +0000 (20:04 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 7 Sep 2006 20:04:10 +0000 (20:04 +0000)
dependencies within circular flushes to work properly...updated
task traversal/logging implementation

this work is still under construction !  requires more unit tests and
new dumper needs to be finished.

CHANGES
lib/sqlalchemy/orm/unitofwork.py
lib/sqlalchemy/orm/uowdumper.py

diff --git a/CHANGES b/CHANGES
index 8ec7f60e9f17e7c14d7d70a98773e5751bb918d9..3ce07ba9cf85ded5ba219a3ba93a599d2ecf2561 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+0.2.9
+- more rearrangements of unit-of-work commit scheme to better allow
+dependencies within circular flushes to work properly...updated
+task traversal/logging implementation
+
 0.2.8
 - cleanup on connection methods + documentation.  custom DBAPI
 arguments specified in query string, 'connect_args' argument
index c0bb219a32e1e6056fabefb0f9daa72f1fe8372b..17c77785a60852cac6b152a3fe66af2b830158de 100644 (file)
@@ -516,6 +516,71 @@ class UOWDependencyProcessor(object):
     def branch(self, task):
         return UOWDependencyProcessor(self.processor, task)
 
+class UOWExecutor(object):
+    def execute(self, trans, task, isdelete=None):
+        if isdelete is not True:
+            self.execute_save_steps(trans, task)
+        if isdelete is not False:
+            self.execute_delete_steps(trans, task)
+
+    def save_objects(self, trans, task):
+        task._save_objects(trans)
+
+    def delete_objects(self, trans, task):
+        task._delete_objects(trans)
+    
+    def execute_dependency(self, trans, dep, isdelete):
+        dep.execute(trans, isdelete)
+        
+    def execute_save_steps(self, trans, task):
+        if task.circular is not None:
+            self.execute_save_steps(trans, task.circular)
+        else:
+            self.save_objects(trans, task)
+            self.execute_cyclical_dependencies(trans, task, False)
+            self.execute_per_element_childtasks(trans, task, False)
+            self.execute_dependencies(trans, task, False)
+            self.execute_dependencies(trans, task, True)
+            self.execute_childtasks(trans, task, False)
+                
+    def execute_delete_steps(self, trans, task):    
+        if task.circular is not None:
+            self.execute_delete_steps(trans, task.circular)
+        else:
+            self.execute_cyclical_dependencies(trans, task, True)
+            self.execute_childtasks(trans, task, True)
+            self.execute_per_element_childtasks(trans, task, True)
+            self.delete_objects(trans, task)
+
+    def execute_dependencies(self, trans, task, isdelete=None):
+        alltasks = list(task.polymorphic_tasks())
+        if isdelete is not True:
+            for task in alltasks:
+                for dep in task.dependencies:
+                    self.execute_dependency(trans, dep, False)
+        if isdelete is not False:
+            alltasks.reverse()
+            for task in alltasks:
+                for dep in task.dependencies:
+                    self.execute_dependency(trans, dep, True)
+
+    def execute_childtasks(self, trans, task, isdelete=None):
+        for polytask in task.polymorphic_tasks():
+            for child in polytask.childtasks:
+                self.execute(trans, child, isdelete)
+                
+    def execute_cyclical_dependencies(self, trans, task, isdelete):
+        for polytask in task.polymorphic_tasks():
+            for dep in polytask.cyclical_dependencies:
+                self.execute_dependency(trans, dep, isdelete)
+                
+    def execute_per_element_childtasks(self, trans, task, isdelete):
+        for polytask in task.polymorphic_tasks():
+            for element in polytask.tosave_elements + polytask.todelete_elements:
+                for child in element.childtasks:
+                    self.execute(trans, child, isdelete)
+    
+    
 class UOWTask(object):
     """represents the full list of objects that are to be saved/deleted by a specific Mapper."""
     def __init__(self, uowtransaction, mapper, circular_parent=None):
@@ -600,56 +665,12 @@ class UOWTask(object):
     def _delete_objects(self, trans):
         for task in self.polymorphic_tasks():
             task.mapper.delete_obj(task.todelete_objects, trans)
-    def _execute_dependencies(self, trans):
-        alltasks = list(self.polymorphic_tasks())
-        for task in alltasks:
-            for dep in task.dependencies:
-                dep.execute(trans, False)
-        alltasks.reverse()
-        for task in alltasks:
-            for dep in task.dependencies:
-                dep.execute(trans, True)
-    def _execute_childtasks(self, trans):
-        for task in self.polymorphic_tasks():
-            for child in task.childtasks:
-                child.execute(trans)
-    def _execute_cyclical_dependencies(self, trans, isdelete):
-        for task in self.polymorphic_tasks():
-            for dep in task.cyclical_dependencies:
-                dep.execute(trans, isdelete)
-    def _execute_per_element_childtasks(self, trans, isdelete):
-        for ptask in self.polymorphic_tasks():
-            if isdelete:
-                for element in ptask.todelete_elements:
-                    for task in element.childtasks:
-                        task.execute(trans)
-            else:
-                for element in ptask.tosave_elements:
-                    for task in element.childtasks:
-                        task.execute(trans)
             
     def execute(self, trans):
         """executes this UOWTask.  saves objects to be saved, processes all dependencies
         that have been registered, and deletes objects to be deleted. """
         
-        # a "circular" task is a circularly-sorted collection of UOWTask/UOWTaskElements
-        # derived from the components of this UOWTask, which accounts for inter-row dependencies.  
-        # if one was created for this UOWTask, it replaces the execution for this UOWTask.
-        if self.circular is not None:
-            self.circular.execute(trans)
-            return
-
-        # TODO: add a visitation system to the UOW classes and have this execution called
-        # from a separate executor object ? (would also handle dumping)
-        
-        self._save_objects(trans)
-        self._execute_cyclical_dependencies(trans, False)
-        self._execute_per_element_childtasks(trans, False)
-        self._execute_dependencies(trans)
-        self._execute_cyclical_dependencies(trans, True)
-        self._execute_childtasks(trans)
-        self._execute_per_element_childtasks(trans, True)
-        self._delete_objects(trans)
+        UOWExecutor().execute(trans, self)
 
     def polymorphic_tasks(self):
         """returns an iteration consisting of this UOWTask, and all UOWTasks whose 
index ab7a1449a275d4e2f43e07b9f2db32c3e247f66d..f49c35d7f059acdb0c260f3ee955596298aae901 100644 (file)
@@ -1,13 +1,83 @@
+import unitofwork
 
 """dumps out a string representation of a UOWTask structure"""
 
-class UOWDumper(object):
+class UOWDumper(unitofwork.UOWExecutor):
     def __init__(self, task, buf, verbose=False):
         self.verbose = verbose
         self.indent = 0
         self.task = task
         self.buf = buf
+        self.starttask = task
+        #self.execute(None, task)
         self._dump(task)
+
+    # execute stuff is UNDER CONSTRUCTION
+    
+    def execute(self, trans, task, isdelete=None):
+        oldstarttask = self.starttask
+        self.starttask = task
+        try:
+            i = self._indent()
+            if len(i):
+                i = i[0:-1] + "-"
+            if task.circular is not None:
+                self.buf.write(self._indent() + "\n")
+                self.buf.write(i + " " + self._repr_task(task))
+                self.buf.write("->circular->" + self._repr_task(task.circular))
+            else:
+                self.buf.write(self._indent() + "\n")
+                self.buf.write(i + " " + self._repr_task(task))
+            self.buf.write("\n")
+            super(UOWDumper, self).execute(trans, task, isdelete)
+        finally:
+            self.starttask = oldstarttask
+            
+    def save_objects(self, trans, task):
+        for rec in task.tosave_elements:
+            if rec.listonly:
+                continue
+            if self.verbose:
+                header(self.buf, self._indent() + "  |- Save elements"+ self._inheritance_tag(task) + "\n")
+            self.buf.write(self._indent() + "  |- " + self._repr_task_element(rec)  + "\n")
+
+    def delete_objects(self, trans, task):
+        for rec in task.todelete_elements:
+            if rec.listonly:
+                continue
+            if self.verbose:
+                header(self.buf, self._indent() + "  |- Delete elements"+ self._inheritance_tag(task) + "\n")
+            self.buf.write(self._indent() + "  |- " + self._repr_task_element(rec)  + "\n")
+
+    def _inheritance_tag(self, task):
+        if not self.verbose:
+            return ""
+        elif task is not self.starttask:
+            return (" (inheriting task %s)" % self._repr_task(task))
+        else:
+            return ""
+
+    def execute_dependency(self, transaction, dep, isdelete):
+        #self.buf.write()
+        pass
+
+    def execute_save_steps(self, trans, task):
+        super(UOWDumper, self).execute_save_steps(trans, task)
+
+    def execute_delete_steps(self, trans, task):    
+        super(UOWDumper, self).execute_delete_steps(trans, task)
+
+    def execute_dependencies(self, trans, task, isdelete=None):
+        super(UOWDumper, self).execute_dependencies(trans, task, isdelete)
+
+    def execute_childtasks(self, trans, task, isdelete=None):
+        super(UOWDumper, self).execute_childtasks(trans, task, isdelete)
+
+    def execute_cyclical_dependencies(self, trans, task, isdelete):
+        super(UOWDumper, self).execute_cyclical_dependencies(trans, task, isdelete)
+
+    def execute_per_element_childtasks(self, trans, task, isdelete):
+        super(UOWDumper, self).execute_per_element_childtasks(trans, task, isdelete)
         
     def _dump_processor(self, proc, deletes):
         if deletes:
@@ -144,6 +214,7 @@ class UOWDumper(object):
             self._dump(starttask.circular, indent=self.indent, circularparent=starttask)
             return
 
+
         i = self._indent()
         if len(i):
             i = i[0:-1] + "-"
@@ -185,3 +256,5 @@ class UOWDumper(object):
             self.buf.write(self._indent() + "  |----\n")
         
         self.buf.write(self._indent() + "\n")           
+
+