[Zope-CVS] SVN: zversioning/trunk/src/versioning/ interfaces added

Uwe Oestermeier uwe_oestermeier at iwm-kmrc.de
Mon Oct 11 09:33:23 EDT 2004


Log message for revision 27974:
  interfaces added


Changed:
  A   zversioning/trunk/src/versioning/interfaces.py
  A   zversioning/trunk/src/versioning/storage.py


-=-
Added: zversioning/trunk/src/versioning/interfaces.py
===================================================================
--- zversioning/trunk/src/versioning/interfaces.py	2004-10-11 13:21:53 UTC (rev 27973)
+++ zversioning/trunk/src/versioning/interfaces.py	2004-10-11 13:33:23 UTC (rev 27974)
@@ -0,0 +1,126 @@
+"""  Whether the versioning scheme uses the existing ZODB or some
+other versioning system like CVS or Subversion as a subsystem
+should be configurable.  How the repository stores the data, 
+whether it is able to version metadata or only content, 
+whether it uses revision numbers for commits
+(like Subversion) or document specific version numbers (like CVS)
+may thus vary.        
+               
+Therefore we use a ticket mechanism, which means that
+the versioning repository takes any versionable data (not necessarily
+the original object), stores them whereever it likes and gives
+back arbitrary access information (a path, a global unique id) which
+is sufficient to guarantee that the provided versionable data
+can be retrieved.
+
+It's the responsibility of the clients to bookkeep this access information 
+or tickets. The inner structure of these tickets cannot be
+determined in advance. We therefore propose only a marker interface
+for this.
+    
+To abstract from the access is simple, more difficult
+is the question, what happens if the used repository allows 
+to generate new version independently from Zope.
+For instance, if someone uses Subversion
+as a backend for versioning, numerous other clients can access 
+the versioned contents and commit changes, if they are allowed.
+
+The important distinction here is that some repositories
+are passive and only wait for versions that were created in Zope.
+Other versioning system may create their own versions of objects
+which must be recognized and be read into Zope. In this case
+there must be a mechanism that informs the involved Zope
+objects about new versions. We propose to use the Zope event system 
+to allow versionable objects to subscribe to new versions if the
+used backend generates its own versions."""
+
+
+   
+class IVersionableData(Interface) :
+    """ An interface that implements a versioning policy for
+        a content type and a storage that knows how to version the
+        content data.
+    """
+           
+ 
+class ITicket(Interface) :
+    """ A marker interface for access information for versioned data.
+    
+        A must provide sufficient information to get back these data.  
+        A ticket is created when some versionable data have been accepted 
+        and successfully stored in the repository.
+    
+        XXX: Special case IDelayedTicket for asynchronous storages needed?
+      
+    """
+
+class IHistoryStorage(Interface) :
+    """ Minimal interface for a pluggable storage that stores a new version
+    of an object into an object history.
+    """
+
+    def register(obj) :
+        """ Puts some object under version control. Returns an ITicket
+        to the first version.
+        """
+    
+    def write(obj) :
+        """ Saves a new version in the repository and returns an ITicket.
+        
+        Raises a VersionControlError if something went wrong.
+        """
+    
+    def read(ticket) :
+        """ Reads a version from the repository that is specified by the ticket.
+        
+        Raises a VersionPermanentlyDeleted exception if the repository
+        allowed to delete the specified version.
+        
+        VersionNotAvailable error if something went wrong 
+        """
+       
+   
+class IPythonReferenceStorage :
+    """ Marker interface for a storage that is able to preserve 
+        python references and thus is able to accept originals.
+    
+        A minimal implementation would only ensure that versioned originals
+        are referenced and thus protected against sweep out in ZODB
+        packs.
+    """
+
+
+   
+class IDeletableStorage(IStorage) :
+    """ Most versioning systems do not allow to throw away versioned
+    data, but there might be use cases were simple file repositories
+    or other storage solutions can sweep out old versions. """
+
+    def delete(obj, ticket) :
+        """ Forces the repository to remove the version described by the ticket.
+        
+            Raises a VersionUndeletable error if the repository does not
+            allow deletions or something other went wrong.
+        """
+
+   
+class IMultiClientStorage(Interface) : 
+    """ if the repository allows several ways to
+    create versions and not only reacts to Zope calls.
+    """
+
+    def triggerEvents(ticket=None) :
+        """ Induce the repository to activate events, 
+        i.e. descriptions of changes that allow the application 
+        to decide whether the zope database must be updated or not.
+        
+        If ticket is specified only the changes of the 
+        referenced object should be described.
+        
+        If ticket is None all changes should be described.   
+        """
+
+
+# XXX describe Event types here
+
+

Added: zversioning/trunk/src/versioning/storage.py
===================================================================
--- zversioning/trunk/src/versioning/storage.py	2004-10-11 13:21:53 UTC (rev 27973)
+++ zversioning/trunk/src/versioning/storage.py	2004-10-11 13:33:23 UTC (rev 27974)
@@ -0,0 +1,131 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+
+from datetime import datetime
+  
+import persistent
+from BTrees.OOBTree import OOBTree
+from BTrees.OIBTree import OIBTree
+
+class TemporalParadox(Exception): pass
+  
+  
+class Version(object) :
+    """ Contains a pointer to the versioned data as well
+        as some metadata.
+    """
+   
+    implents(IVersion)
+    
+    def __init__(self, data, metadata) :
+        self.data = data
+        self.when = datetime.datetime(metadata["time"])
+        self.who = metadata["user_name"]
+        self.description = metadata["description"]
+    
+    
+class HistoryStorageMixin(object) :
+
+    _histories = None
+
+    def getTicket(self, obj) :
+        raise NotImplementedError
+
+    def getHistory(self, obj) :
+        """ Returns the history for a versionable object. """  
+        ticket = self.getTicket()
+        if self.hasHistory(
+         
+    def load(self, obj, selector) :
+        
+   
+    def save(self, obj) :
+    
+  
+   
+      
+class SimpleHistoryStorage(Persistent) :
+    """ We simply use the ZODB history for our references to
+        revisions of an object.
+      
+    """
+    
+    def __init__(self) :
+        self._histories = OIBTree()
+    
+    def getTicket(self, obj) :
+        return obj._p_oid
+            
+    
+        
+        
+# 
+# 
+# class HystoryJar(object) :
+#     """A ZODB Connection-like object that provides access to data
+#     but prevents history from being changed.
+#     
+#     Shamelessly copied from Zope2 OFS.History and thus ported to Zope3
+#   
+#     XXX is there something in Zope3 that already corresponds to this.
+#     """
+# 
+#     def __init__(self, base):
+#         self.__base__=base
+# 
+#     def __getattr__(self, name):
+#         return getattr(self.__base__, name)
+# 
+#     def commit(self, object, transaction):
+#         if object._p_changed:
+#             raise TemporalParadox, "You can't change history!"
+# 
+#     def abort(*args, **kw): pass
+# 
+#     tpc_begin = tpc_finish = abort
+#     
+#          
+#     def _getVersionFromHistory(self, ticket, revision):
+#         """ Retrieves a revision from a history of an object. """
+#         
+#         serial=revision['serial']
+#         state=ticket._p_jar.oldstate(self, serial)
+#         rev=ticket.__class__.__basicnew__()
+#         rev._p_jar=HystoryJar(ticket._p_jar)
+#         rev._p_oid=ticket._p_oid
+#         rev._p_serial=serial
+#         rev.__setstate__(state)
+#         rev._p_changed=0
+#        
+#         return IVersion(rev, revision)
+#         
+#     def getVersions(obj):
+#         """Get a list of versions."""
+#         revisions = obj._p_jar.db().history(self._p_oid, None, 20)
+#         if revisions is None:
+#             return ()
+#         return [self._getVersionFromHistory(r) for r in revisions]
+#         
+
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocTestSuite(),
+        ))
+        
+        
+if __name__=='__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Zope-CVS mailing list