[Zope3-checkins] CVS: Zope3/src/zodb/zeo - client.py:1.3.4.1 server.py:1.4.4.1

Jeremy Hylton jeremy@zope.com
Tue, 4 Feb 2003 17:54:49 -0500


Update of /cvs-repository/Zope3/src/zodb/zeo
In directory cvs.zope.org:/tmp/cvs-serv6570/src/zodb/zeo

Modified Files:
      Tag: storage-interface-branch
	client.py server.py 
Log Message:
Refactor storage interfaces.

Move a bunch of exceptions related to storages from zodb.interfaces to
zodb.storages.interfaces.

Add __implements__ statements in all the concrete storage classes.

Add a simple (good?) mechanism to propagate __implements__ values from
a ZEO storage to its clients.

Remove all use of supportsXXX() methods in favor of
ISomeInterface.isImplementedBy().


=== Zope3/src/zodb/zeo/client.py 1.3 => 1.3.4.1 ===
--- Zope3/src/zodb/zeo/client.py:1.3	Fri Jan 24 18:20:49 2003
+++ Zope3/src/zodb/zeo/client.py	Tue Feb  4 17:54:17 2003
@@ -41,7 +41,7 @@
 from zodb.zeo.tbuf import TransactionBuffer
 from zodb.zeo.zrpc.client import ConnectionManager
 
-from zodb import interfaces
+from zodb.storage.interfaces import *
 from zodb.timestamp import TimeStamp
 
 try:
@@ -49,7 +49,7 @@
 except ImportError:
     ResolvedSerial = 'rs'
 
-class ClientStorageError(interfaces.StorageError):
+class ClientStorageError(StorageError):
     """An error occured in the ZEO Client Storage."""
 
 class UnrecognizedResult(ClientStorageError):
@@ -105,6 +105,13 @@
     ConnectionManagerClass = ConnectionManager
     StorageServerStubClass = stubs.StorageServer
 
+    # The exact storage interfaces depend on the server that the client
+    # connects to.  We know that every storage must implement IStorage,
+    # but once connected we may change the instance's __implements__
+    # to reflect features available on the storage.
+    
+    __implements__ = IStorage
+
     def __init__(self, addr, storage='1', cache_size=20 * MB,
                  name='', client=None, debug=0, var=None,
                  min_disconnect_poll=5, max_disconnect_poll=300,
@@ -210,10 +217,8 @@
         # _server_addr is used by sortKey()
         self._server_addr = None
 
-        self._info = {'length': 0, 'size': 0, 'name': 'ZEO Client',
-                      'supportsUndo':0, 'supportsVersions': 0,
-                      'supportsTransactionalUndo': 0}
-
+        self._info = {'length': 0, 'size': 0, 'name': 'ZEO Client'}
+        
         self._tbuf = self.TransactionBufferClass()
         self._db = None
 
@@ -325,7 +330,7 @@
         try:
             stub.register(str(self._storage), self._is_read_only)
             return 1
-        except interfaces.ReadOnlyError:
+        except ReadOnlyError:
             if not self._read_only_fallback:
                 raise
             self.logger.warn(
@@ -347,6 +352,7 @@
         stub = self.StorageServerStubClass(conn)
         self._oids = []
         self._info.update(stub.get_info())
+        self.update_interfaces()
         self.verify_cache(stub)
 
         # XXX The stub should be saved here and set in endVerify() below.
@@ -355,6 +361,16 @@
         self._connection = conn
         self._server = stub
 
+    def update_interfaces(self):
+        # Update instance's __implements__ based on the server.
+        L = [IStorage]
+        for name in self._info.get("implements", ()):
+            if name == "IUndoStorage":
+                L.append(IUndoStorage)
+            elif name == "IVersionStorage":
+                L.append(IVersionStorage)
+        self.__implements__ = tuple(L)
+
     def set_server_addr(self, addr):
         # Normalize server address and convert to string
         if isinstance(addr, types.StringType):
@@ -433,18 +449,6 @@
         """
         return self._info['extensionMethods']
 
-    def supportsUndo(self):
-        """Storage API: return whether we support undo."""
-        return self._info['supportsUndo']
-
-    def supportsVersions(self):
-        """Storage API: return whether we support versions."""
-        return self._info['supportsVersions']
-
-    def supportsTransactionalUndo(self):
-        """Storage API: return whether we support transactional undo."""
-        return self._info['supportsTransactionalUndo']
-
     def isReadOnly(self):
         """Storage API: return whether we are in read-only mode.
 
@@ -464,10 +468,9 @@
     def _check_trans(self, trans):
         """Internal helper to check a transaction argument for sanity."""
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if self._transaction is not trans:
-            raise interfaces.StorageTransactionError(self._transaction,
-                                                       trans)
+            raise StorageTransactionError(self._transaction, trans)
 
     def abortVersion(self, version, transaction):
         """Storage API: clear any changes made by the given version."""
@@ -553,7 +556,7 @@
     def new_oid(self):
         """Storage API: return a new object identifier."""
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         # avoid multiple oid requests to server at the same time
         self._oid_lock.acquire()
         try:
@@ -613,7 +616,7 @@
     def tpc_begin(self, txn, tid=None, status=' '):
         """Storage API: begin a transaction."""
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         self._tpc_cond.acquire()
         while self._transaction is not None:
             # It is allowable for a client to call two tpc_begins in a
@@ -739,7 +742,7 @@
     def undo(self, transaction_id):
         """Storage API: undo a transaction, writing directly to the storage."""
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         # XXX what are the sync issues here?
         oids = self._server.undo(transaction_id)
         for oid in oids:


=== Zope3/src/zodb/zeo/server.py 1.4 => 1.4.4.1 ===
--- Zope3/src/zodb/zeo/server.py:1.4	Fri Jan 24 18:20:49 2003
+++ Zope3/src/zodb/zeo/server.py	Tue Feb  4 17:54:17 2003
@@ -34,8 +34,10 @@
 from zodb.zeo.zrpc.connection import ManagedServerConnection, Delay, MTDelay
 
 from zodb.ztransaction import Transaction
-from zodb.interfaces import StorageError, StorageTransactionError
-from zodb.interfaces import TransactionError, ReadOnlyError
+from zodb.interfaces import TransactionError
+from zodb.storage.interfaces import *
+
+from zope.interface.implements import objectImplements
 
 class StorageServerError(StorageError):
     """Error reported when an unpickleable exception is raised."""
@@ -241,7 +243,6 @@
         self.setVersion = self.storage.setVersion
         self.versionEmpty = self.storage.versionEmpty
         self.versions = self.storage.versions
-        self.history = self.storage.history
         self.load = self.storage.load
         self.loadSerial = self.storage.loadSerial
         self.modifiedInVersion = self.storage.modifiedInVersion
@@ -302,11 +303,10 @@
         self.server.register_connection(storage_id, self)
 
     def get_info(self):
-        return {'name': self.storage.getName(),
-                'supportsVersions': self.storage.supportsVersions(),
-                'supportsTransactionalUndo':
-                self.storage.supportsTransactionalUndo(),
-                'extensionMethods': self.getExtensionMethods(),
+        return {"name": self.storage.getName(),
+                "implements": [iface.__name__
+                               for iface in objectImplements(self.storage)],
+                "extensionMethods": self.getExtensionMethods(),
                 }
 
     def getExtensionMethods(self):