[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