[Zope-CVS] CVS: Packages/pypes/pypes - event.py:1.6 extent.py:1.8 identity.py:1.15 interfaces.py:1.14 serviceconfig.py:1.4 services.py:1.6

Casey Duncan casey at zope.com
Sun Mar 7 05:09:44 EST 2004


Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv26459/pypes

Modified Files:
	event.py extent.py identity.py interfaces.py serviceconfig.py 
	services.py 
Log Message:
* Create util module and tests for shared functions, refactor other modules to use new functions
* Add attach() function to services to replace connection.add() for cases where we want service access without adding to the database.
* Add accesspointFrom() function to abstract service access better, refactor other code to use it


=== Packages/pypes/pypes/event.py 1.5 => 1.6 ===
--- Packages/pypes/pypes/event.py:1.5	Wed Mar  3 23:29:45 2004
+++ Packages/pypes/pypes/event.py	Sun Mar  7 05:09:12 2004
@@ -24,6 +24,7 @@
 from zope.interface import implements
 from pypes.interfaces import IEventService
 from pypes.exceptions import EventRegistrationError
+from pypes.util import mro, classKey, classFromKey
 
 
 class PypesMessage(object):
@@ -53,7 +54,7 @@
             raise TypeError, 'Event listener method registered is not callable'
         if not isinstance(message_type, (type, ClassType)):
             raise TypeError, 'Event listener message_type must be type or class'
-        type_key = _msgTypeKey(message_type)
+        type_key = classKey(message_type)
         pair = (WeakRef(obj), method_name)
         try:
             reglist = self._listeners[type_key]
@@ -65,7 +66,7 @@
             self._listeners[type_key] = reglist # trigger persistence
     
     def unregisterListener(self, obj, method_name, message_type):
-        type_key = _msgTypeKey(message_type)
+        type_key = classKey(message_type)
         try:
             listeners = self._listeners[type_key]
             listeners.remove((WeakRef(obj), method_name))
@@ -79,7 +80,7 @@
     
     def unregisterAllListeners(self, message_type):
         try:
-            del self._listeners[_msgTypeKey(message_type)]
+            del self._listeners[classKey(message_type)]
         except KeyError:
             pass
             
@@ -96,7 +97,7 @@
         
     def isListener(self, obj, message_type):
         try:
-            reglist = self._listeners[_msgTypeKey(message_type)]
+            reglist = self._listeners[classKey(message_type)]
         except KeyError:
             return False
         else:
@@ -106,9 +107,9 @@
         return False            
 
     def wouldReceive(self, obj, message_type):
-        for super_type in _mro(message_type):
+        for super_type in mro(message_type):
             try:
-                reglist = self._listeners[_msgTypeKey(super_type)]
+                reglist = self._listeners[classKey(super_type)]
             except KeyError:
                 continue
             for listener, name in self._iterRegistrations(reglist):
@@ -118,7 +119,7 @@
         
     def iterListeners(self, message_type):
         try:
-            reglist = self._listeners[_msgTypeKey(message_type)]
+            reglist = self._listeners[classKey(message_type)]
         except KeyError:
             # Nothing is registered for this type
             return iter(())
@@ -132,9 +133,9 @@
         
     def iterReceivers(self, message_type):
         rlists = []
-        for super_type in _mro(message_type):
+        for super_type in mro(message_type):
             try:
-                rlists.append(self._listeners[_msgTypeKey(super_type)])
+                rlists.append(self._listeners[classKey(super_type)])
             except KeyError:
                 continue
         if len(rlists) == 1:
@@ -161,24 +162,9 @@
     
     def iterMessageTypes(self):
         for typekey in self._listeners.keys():
-            yield _msgTypeFromKey(typekey)
+            yield classFromKey(typekey)
     
     # XXX Need to add mechanism to clean stale listener references
     # perhaps this should be opportunistic as part of registerListener
     # or a separate method or both
 
-def _mro(typeobj):
-    """Calculate and return the method resolution order. Works for
-    both new style type/classes and classic classes
-    """
-    try:
-        return typeobj.mro()
-    except AttributeError:
-        # Old style class
-        # XXX need to find a better spelling
-        class NewStyle(typeobj, object):
-            pass
-        return NewStyle.mro()[1:-1]
-
-_msgTypeKey = cPickle.dumps
-_msgTypeFromKey = cPickle.loads


=== Packages/pypes/pypes/extent.py 1.7 => 1.8 ===
--- Packages/pypes/pypes/extent.py:1.7	Sun Feb 29 00:44:48 2004
+++ Packages/pypes/pypes/extent.py	Sun Mar  7 05:09:12 2004
@@ -29,6 +29,7 @@
 from pypes.interfaces import IExtentService, IExtentMap
 from pypes.interfaces import IExtent, ICanonicalExtent, IDerivedExtent
 from pypes.exceptions import SetLookupError
+from pypes.util import mro, classKey, classFromKey
 
 
 class Extent:
@@ -199,7 +200,7 @@
         self._subclasses = OOBTree() # Map class key => set of subclass keys
         self._instances = OOBTree() # Map class key => id set of instances
         listenForIdEvents(self, dbconn)
-        dbconn.add(self) # Allow service access before commit
+        services.attach(self, dbconn) # Allow service access before commit
         #self.update(dbconn)
     
     def __getitem__(self, key):
@@ -216,7 +217,7 @@
     def __iter__(self):
         for key in self._instances.keys():
             # XXX May need to handle mutation
-            yield self[keyClass(key)]
+            yield self[classFromKey(key)]
     
     def update(self):
         raise NotImplementedError
@@ -323,17 +324,3 @@
         for extent_map in self._extent_maps:
             for extent in extent_map:
                 yield extent
-
-
-# XXX These should go to a utils module
-from pypes.event import _mro as mro
-from cPickle import loads
-from cPickle import dumps
-def classKey(obj):
-    if ( isinstance(obj, type) or isinstance(obj, ClassType)):
-        cls = obj
-    else:
-        cls = getattr(obj, '__class__', type(obj))
-    return dumps(cls)
-
-keyClass = loads


=== Packages/pypes/pypes/identity.py 1.14 => 1.15 ===
--- Packages/pypes/pypes/identity.py:1.14	Thu Mar  4 00:09:50 2004
+++ Packages/pypes/pypes/identity.py	Sun Mar  7 05:09:12 2004
@@ -163,7 +163,7 @@
         else:
             set._idset = idset
         if dbconn is not None:
-            dbconn.add(set)
+            services.attach(set, dbconn)
         set._length = Length(len(idset))
         return set
     fromIdSet = classmethod(fromIdSet)
@@ -171,8 +171,8 @@
     def add(self, obj):
         if self._p_jar is None and getattr(obj, '_p_jar', None) is not None:
             # If we are not associated with a database connection
-            # add us to one from the child object so we can access services
-            obj._p_jar.add(self)
+            # attach us to one from the child object so we can access services
+            services.attach(self, obj._p_jar)
         ident = pypesid(obj)
         if ident is None:
             raise IdentityError, obj
@@ -245,19 +245,22 @@
     
     def union(self, other):
         return self.__class__.fromIdSet(
-            union(self._idset, other._idset), dbconn=self._p_jar)
+            union(self._idset, other._idset), 
+                  dbconn=services.accesspointFrom(self))
     
     __or__ = union
     
     def difference(self, other):
         return self.__class__.fromIdSet(
-            difference(self._idset, other._idset), dbconn=self._p_jar)
+            difference(self._idset, other._idset), 
+                       dbconn=services.accesspointFrom(self))
         
     __sub__ = difference
     
     def intersection(self, other):
         return self.__class__.fromIdSet(
-            intersection(self._idset, other._idset), dbconn=self._p_jar)  
+            intersection(self._idset, other._idset), 
+                         dbconn=services.accesspointFrom(self))  
     
     __and__ = intersection
     
@@ -299,7 +302,7 @@
     for set in identity_sets:
         idsets.append(set._idset)
         if dbconn is None:
-            dbconn = getattr(set, '_p_jar', None)
+            dbconn = services.accesspointFrom(set)
     idunion = IIBTree.multiunion(idsets)
     return IdentitySet.fromIdSet(idunion, dbconn=dbconn)
 
@@ -312,7 +315,7 @@
     idsect = None
     for set in identity_sets:
         if dbconn is None:
-            dbconn = getattr(set, '_p_jar', None)
+            dbconn = services.accesspointFrom(set)
         if not set:
             # Short circuit on empty set
             return IdentitySet()


=== Packages/pypes/pypes/interfaces.py 1.13 => 1.14 ===
--- Packages/pypes/pypes/interfaces.py:1.13	Mon Mar  1 01:36:15 2004
+++ Packages/pypes/pypes/interfaces.py	Sun Mar  7 05:09:12 2004
@@ -666,13 +666,13 @@
     execute queries and generate results"""
     
     def inputs():
-        """Return the query inputs and names as a sequence of 
-        (name, input) pairs
-        """
+        """Return the query inputs as a dict keyed by input name"""
         
     def rawResults():
-        """Return the current results in raw form cooresponding to the inputs: 
-        a sequence of (input name, result collection) pairs
+        """Return the current results in raw form as a dict with
+        input name, result sequence as its respective key/value pairs.
+        These results should be suitable for use as inputs for another
+        query engine
         """
         
     def results(projection):


=== Packages/pypes/pypes/serviceconfig.py 1.3 => 1.4 ===
--- Packages/pypes/pypes/serviceconfig.py:1.3	Mon Feb  9 16:14:57 2004
+++ Packages/pypes/pypes/serviceconfig.py	Sun Mar  7 05:09:12 2004
@@ -53,6 +53,8 @@
     registry = connection.root()[registry_name]
     if registry.has_key(name):
         raise PypesError, 'Service %s already exists' % name
+    if service._p_jar is None:
+        connection.add(service)
     registry[name] = service
     
 
@@ -60,6 +62,8 @@
     """Like add service, but will also replace existing services. Use with
     care, since services can contain user data."""
     registry = connection.root()[registry_name]
+    if service._p_jar is None:
+        connection.add(service)
     registry[name] = service
 
 


=== Packages/pypes/pypes/services.py 1.5 => 1.6 ===
--- Packages/pypes/pypes/services.py:1.5	Mon Feb 16 00:54:03 2004
+++ Packages/pypes/pypes/services.py	Sun Mar  7 05:09:12 2004
@@ -33,17 +33,16 @@
 
     Usage: services.get(someobj, 'identity')::
 
-      accesspoint -- An IAppConnection or an IPersistent object. The database
-      connection for the object must be open for the call to succeed.
+      accesspoint -- A zodb connection, and object in the database or an
+      object attached to the conection via the attach() function.
 
       name -- String name of the service.
     """
-    if isinstance(accesspoint, Persistent):
-        accesspoint = accesspoint._p_jar
-    root = accesspoint.root()
+    accesspoint = accesspointFrom(accesspoint)
     try:
+        root = accesspoint.root()
         return root[registry_name][name]
-    except KeyError:
+    except (KeyError, AttributeError):
         raise PypesLookupError, 'Service %s could not be accessed.' % name
 
 
@@ -75,8 +74,7 @@
 
     Usage: svcs = services.all(someobj)
     """
-    if isinstance(accesspoint, Persistent):
-        accesspoint = accesspoint._p_jar
+    accesspoint = accesspointFrom(accesspoint)
     try:
         return dict(accesspoint.root()[registry_name])
     except KeyError:
@@ -84,5 +82,39 @@
     except (AttributeError, TypeError):
         raise PypesLookupError, 'Invalid connection object.'
 
-
-
+def attach(obj, conn):
+    """Attaches obj to the pypes services for conn. obj can then be used as
+    an access point for other services.
+    
+    You can also add the object to the connection to do this, but that
+    persists obj. attach() allows you to attach objects to services without 
+    persisting them immediately. attached objects can still be persisted later 
+    if desired.
+    
+    If obj is already added to conn, do nothing. Raise PypeError if obj is 
+    already attached or added to another connection. Raise TypeError if
+    obj is not persistent
+    """
+    if not isinstance(obj, Persistent):
+        raise TypeError, 'expected persistent instance first argument'
+    obj_conn = getattr(obj, '_p_jar', None)
+    if obj_conn is None:
+        # Object not added to any connection
+        obj._v_pypes_connection_ = conn
+    elif obj_conn is not conn:
+        raise PypesError, 'object already added to another connection'
+
+def accesspointFrom(obj):
+    """Return the service accesspoint (a zodb connection) for obj. obj can
+    be a zodb connection, an object in the database or an object attached to
+    the connection via the attach() function. Return None if
+    obj cannot be used as an accesspoint.
+    """
+    if isinstance(obj, Connection):
+        return obj
+    else:
+        try:
+            return obj._p_jar or obj._v_pypes_connection_
+        except AttributeError:
+            return None
+        




More information about the Zope-CVS mailing list