[Checkins] SVN: z3c.vcsync/trunk/ Added functionality to execute a function for all objects modified/created

Martijn Faassen faassen at infrae.com
Tue Mar 11 17:32:19 EDT 2008


Log message for revision 84593:
  Added functionality to execute a function for all objects modified/created
  during synchronization or import.
  

Changed:
  U   z3c.vcsync/trunk/CHANGES.txt
  U   z3c.vcsync/trunk/src/z3c/vcsync/README.txt
  U   z3c.vcsync/trunk/src/z3c/vcsync/importexport.py
  U   z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py
  U   z3c.vcsync/trunk/src/z3c/vcsync/vc.py

-=-
Modified: z3c.vcsync/trunk/CHANGES.txt
===================================================================
--- z3c.vcsync/trunk/CHANGES.txt	2008-03-11 21:24:14 UTC (rev 84592)
+++ z3c.vcsync/trunk/CHANGES.txt	2008-03-11 21:32:19 UTC (rev 84593)
@@ -14,6 +14,12 @@
   and not remove and recreate objects unnecessarily, which makes it
   harder to implement things like references between objects.
 
+* Add a facility to pass a special function along that is called for
+  all objects created or modified during the synchronization (or
+  during import). This function is called at the end when all objects
+  that are going to exist already exist, so can be used in situations
+  where the state of an object relies on the existence of another one.
+
 0.11 (2008-03-10)
 -----------------
 

Modified: z3c.vcsync/trunk/src/z3c/vcsync/README.txt
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/README.txt	2008-03-11 21:24:14 UTC (rev 84592)
+++ z3c.vcsync/trunk/src/z3c/vcsync/README.txt	2008-03-11 21:32:19 UTC (rev 84593)
@@ -462,7 +462,7 @@
 
 We can now do the loading::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
 
 We expect the proper objects to be in the new container::
 
@@ -515,7 +515,7 @@
 
 We will reload the checkout into Python objects::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
  
 We expect the ``hoi`` object to be modified::
 
@@ -541,7 +541,7 @@
 
 We will reload the checkout into Python objects again::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
  
 We expect there to be a new object ``hallo``::
 
@@ -566,7 +566,7 @@
 
 We will reload the checkout into Python objects::
   
-  >>> s.load(None)
+  >>> dummy = s.load(None)
 
 We expect the object ``hallo`` to be gone again::
 
@@ -595,7 +595,7 @@
 
 Reloading this will cause a new container to exist::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
   >>> 'newdir' in container2.keys()
   True
   >>> isinstance(container2['newdir'], Container)
@@ -621,7 +621,7 @@
 
 And reload the data::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
 
 Reloading this will cause the new container to be gone again::
 
@@ -651,7 +651,7 @@
 
 Reloading this will cause a new container to be there instead of the file::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
   >>> isinstance(container2['hoi'], Container)
   True
   >>> container2['hoi']['some'].payload
@@ -679,7 +679,7 @@
 Reloading this will cause a new item to be there instead of the
 container::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
   >>> isinstance(container2['hoi'], Item)
   True
   >>> container2['hoi'].payload
@@ -735,7 +735,7 @@
 Reloading this will cause a new type of item to be there instead of the old
 type::
 
-  >>> s.load(None)
+  >>> dummy = s.load(None)
   >>> isinstance(container2['hoi'], Item2)
   True
   >>> container2['hoi'].payload
@@ -774,9 +774,14 @@
   >>> checkout.revision_nr()
   8
 
-Now we'll synchronize with the memory structure::
+Now we'll synchronize with the memory structure. We'll pass a special
+function along that prints out all objects that have been created or
+modified::
 
-  >>> info = s.sync(None)
+  >>> def f(obj):
+  ...   print "modified:", obj.__name__
+  >>> info = s.sync(None, message='', modified_function=f)
+  modified: alpha
   >>> info.revision_nr
   9
 
@@ -887,14 +892,26 @@
 Importing
 ---------
 
-Now we import the state on the filesystem into a fresh container::
+Now we import the state on the filesystem into a fresh container.
 
   >>> container3 = Container()
   >>> container3.__name__ = 'root'
 
   >>> from z3c.vcsync import import_state
-  >>> import_state(TestState(container3), target)
 
+We pass in a special function that prints out all the objects we just
+imported::
+
+  >>> def f(obj):
+  ...   print  obj
+  >>> import_state(TestState(container3), target, modified_function=f)
+  <Item object at ...>
+  <Item object at ...>
+  <z3c.vcsync.tests.Container object at ...>
+  <Item object at ...>
+  <Item object at ...>
+
+
 We expect the structure to be the same as what we exported::
 
   >>> sorted(container3.keys())

Modified: z3c.vcsync/trunk/src/z3c/vcsync/importexport.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/importexport.py	2008-03-11 21:24:14 UTC (rev 84592)
+++ z3c.vcsync/trunk/src/z3c/vcsync/importexport.py	2008-03-11 21:32:19 UTC (rev 84593)
@@ -34,10 +34,14 @@
     else:
         zf.write(path.strpath, path.relto(save_path))
 
-def import_state(state, path):
-    import_helper(state.root, path)
-    
+def import_state(state, path, modified_function=None):
+    modified_objects = import_helper(state.root, path)
+    if modified_function is not None:
+        for obj in modified_objects:
+            modified_function(obj)
+
 def import_helper(obj, path):
+    modified_objects = []
     for p in path.listdir():
         factory = getUtility(IVcFactory, name=p.ext)
         name = p.purebasename
@@ -45,8 +49,11 @@
             obj[name] = new_obj = factory(p)
         else:
             new_obj = obj[name]
+        modified_objects.append(new_obj)
         if p.check(dir=True) and IContainer.providedBy(new_obj):
-            import_helper(new_obj, p)
+            r = import_helper(new_obj, p)
+            modified_objects.extend(r)
+    return modified_objects
 
 def import_state_zip(state, name, zippath):
     tmp_dir = py.path.local(tempfile.mkdtemp())

Modified: z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py	2008-03-11 21:24:14 UTC (rev 84592)
+++ z3c.vcsync/trunk/src/z3c/vcsync/interfaces.py	2008-03-11 21:32:19 UTC (rev 84593)
@@ -135,7 +135,7 @@
     checkout = Attribute('Version control system checkout')
     state = Attribute('Persistent state')
     
-    def sync(revision_nr, message=''):
+    def sync(revision_nr, message='', modified_function=None):
         """Synchronize persistent Python state with version control system.
 
         revision_nr - Revision number since when we want to synchronize.
@@ -145,7 +145,9 @@
              as the ZODB by this revision number.  Normally a version
              control system such as SVN controls these.
         message - message to commit any version control changes.
-
+        modified_function - a function that takes a single parameter.
+             It is called for each object that is modified or created
+             in the state during the synchronization process. (optional)
         Returns a ISynchronizationInfo object with a report of the
         synchronization, including the new revision number after 
         synchronization.
@@ -161,6 +163,9 @@
         """Load the filesystem information into persistent state.
 
         revision_nr - revision_nr after which to look for filesystem changes.
+
+        Returns all the objects in the state that were modified/created due
+        to the synchronization process.
         """
 
 class ISynchronizationInfo(Interface):

Modified: z3c.vcsync/trunk/src/z3c/vcsync/vc.py
===================================================================
--- z3c.vcsync/trunk/src/z3c/vcsync/vc.py	2008-03-11 21:24:14 UTC (rev 84592)
+++ z3c.vcsync/trunk/src/z3c/vcsync/vc.py	2008-03-11 21:32:19 UTC (rev 84593)
@@ -105,7 +105,7 @@
         self.state = state
         self._to_remove = []
 
-    def sync(self, revision_nr, message=''):
+    def sync(self, revision_nr, message='', modified_function=None):
         # store these to report in SynchronizationInfo below
         objects_removed = list(self.state.removed(revision_nr))
         root = self.state.root
@@ -130,7 +130,11 @@
         files_removed = self.checkout.removed(revision_nr)
         files_changed = self.checkout.files(revision_nr)
         # now load the checkout state back into the ZODB state
-        self.load(revision_nr)
+        modified_objects = self.load(revision_nr)
+        # do a final pass with the modified_function if necessary
+        if modified_function is not None:
+            for obj in modified_objects:
+                modified_function(obj)
         # and commit the checkout state
         self.checkout.commit(message)
         return SynchronizationInfo(self.checkout.revision_nr(),
@@ -189,6 +193,7 @@
         file_paths = self.checkout.files(revision_nr)
         # to ensure that containers are created before items we sort them
         file_paths.sort()
+        modified_objects = []
         for file_path in file_paths:
             # we might get something that doesn't actually exist anymore
             # as it was since removed, so skip it
@@ -208,7 +213,9 @@
             else:
                 factory = getUtility(IVcFactory, name=ext)
                 container[name] = factory(file_path)
-
+            modified_objects.append(container[name])
+        return modified_objects
+    
     def _get_container_path(self, root, obj):
         steps = []
         while obj is not root:



More information about the Checkins mailing list