[Zope-CVS] CVS: Packages/pypes/pypes - extent.py:1.3

Casey Duncan casey at zope.com
Sun Feb 15 23:45:28 EST 2004


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

Modified Files:
	extent.py 
Log Message:
Implement Extent class.


=== Packages/pypes/pypes/extent.py 1.2 => 1.3 ===
--- Packages/pypes/pypes/extent.py:1.2	Tue Feb 10 01:25:36 2004
+++ Packages/pypes/pypes/extent.py	Sun Feb 15 23:44:57 2004
@@ -19,10 +19,10 @@
 
 from types import ClassType
 from sets import Set
-from zope.interface import implements
+from zope.interface import implements, directlyProvides
 from persistent import Persistent
-from BTrees.OOBTree import OOBTree, OOTreeSet
-from pypes import services
+from BTrees.OOBTree import OOBTree, OOTreeSet, union, difference, intersection
+from pypes import services, identity
 from pypes.identity import IdRegisteredMessage, IdUnregisteredMessage
 from pypes.identity import IdentitySet, listenForIdEvents
 from pypes.interfaces import IExtentService, IExtentMap
@@ -30,9 +30,196 @@
 from pypes.exceptions import SetLookupError
 
 
-class ClassExtent:
-    pass
-
+class Extent:
+    """Dynamic set of identified instances of a specific kind"""
+    
+    # Extents are dynamically created upon request from an extent map
+    # and therefore do not need to be persistent. They are essentially
+    # specific views of the extent map object.
+    
+    implements(IExtent)
+    
+    def __init__(self, qualifiers, instances, key=None):
+        """Create the class extent
+        
+        qualifiers -- A set of keys to the instances map which identifies
+        which kinds of objects are contained in the extent.
+        
+        instances -- A map of type key -> identity set of instances of that 
+        type. These sets must be completely disjoint.
+        
+        key -- The canonical identifier that is the key to the extent
+        in the extent service. If provided this becomes the key attribute
+        of the extent, and it provides the ICanonicalClass interface
+        """
+        if key is not None:
+            self.key = key
+            directlyProvides(self, ICanonicalExtent)
+        self._qualifiers = qualifiers
+        self._instances = instances
+    
+    def __contains__(self, obj):
+        for key in self._qualifiers:
+            try:
+                instances = self._instances[key]
+            except KeyError:
+                pass # No instances for that type
+            else:
+                if obj in instances:
+                    return True
+        return False
+    
+    def __len__(self):
+        length = 0
+        for key in self._qualifiers:
+            try:
+                instances = self._instances[key]
+            except KeyError:
+                pass # No instances for that type
+            else:
+                length += len(instances)
+        return length
+    
+    def __iter__(self):
+        for key in self._qualifiers:
+            try:
+                instances = self._instances[key]
+            except KeyError:
+                pass # No instances for that type
+            else:
+                for obj in instances:
+                    yield obj
+    
+    def union(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:        
+                extent = self.__class__(
+                    union(self._qualifiers, other._qualifiers), 
+                    self._instances)
+                directlyProvides(extent, IDerivedExtent)
+                return extent
+            else:
+                return identity.multiunion(self._listSets(self, other))
+        elif isinstance(other, IdentitySet):
+            return identity.multiunion(self._listSets(self) + other)
+        else:
+            # Assume other is a sequence of identified objects
+            set = identity.multiunion(self._listSets(self))
+            set.update(other)
+            return set
+    
+    __or__ = union
+    
+    def difference(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:        
+                extent = self.__class__(
+                    difference(self._qualifiers, other._qualifiers), 
+                    self._instances)
+                directlyProvides(extent, IDerivedExtent)
+                return extent
+            else:
+                return (identity.multiunion(self._listSets(self))
+                        - identity.multiunion(self._listSets(other)))
+        elif isinstance(other, IdentitySet):
+            return identity.multiunion(self._listSets(self)) - other
+        else:
+            # Assume other is a sequence of identified objects
+            return (identity.multiunion(self._listSets(self))
+                    - IdentitySet(other))
+    
+    __sub__ = difference
+    
+    def intersection(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:
+                extent = self.__class__(
+                    intersection(self._qualifiers, other._qualifiers), 
+                    self._instances)
+                directlyProvides(extent, IDerivedExtent)
+                return extent
+            else:
+                return identity.multiintersection(self._listSets(self, other))
+        elif isinstance(other, IdentitySet):
+            return identity.multiintersection(self._listSets(self) + other)
+        else:
+            # Assume other is a sequence of identified objects
+            sets = self._listSets(self)
+            sets.append(IdentitySet(other))
+            return identity.multiintersection(sets)
+    
+    __and__ = intersection
+    
+    def __invert__(self):
+        inverse_keys = difference(
+            OOTreeSet(self._instances.keys()), self._qualifiers)
+        extent = self.__class__(inverse_keys, self._instances)
+        directlyProvides(extent, IDerivedExtent)
+        return extent
+    
+    def issubset(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:
+                return not difference(self._qualifiers, other._qualifiers)
+            else:
+                self_set = identity.multiintersection(self._listSets(self))
+                other_set = identity.multiintersection(self._listSets(other))
+                return self_set.issubset(other_set)
+        else:
+            self_set = identity.multiintersection(self._listSets(self))
+            return self_set.issubset(other)
+    
+    def issuperset(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:
+                return not difference(other._qualifiers, self._qualifiers)
+            else:
+                self_set = identity.multiintersection(self._listSets(self))
+                other_set = identity.multiintersection(self._listSets(other))
+                return self_set.issuperset(other_set)
+        else:
+            self_set = identity.multiintersection(self._listSets(self))
+            return self_set.issuperset(other)
+    
+    def __eq__(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:
+                return not (difference(self._qualifiers, other._qualifiers) or
+                            difference(other._qualifiers, self._qualifiers))
+            else:
+               self_set = identity.multiintersection(self._listSets(self))
+               other_set = identity.multiintersection(self._listSets(other))
+               return self_set == other_set
+        else:
+            self_set = identity.multiintersection(self._listSets(self))
+            return self_set == other
+    
+    def __ne__(self, other):
+        if isinstance(other, Extent):
+            if self._instances is other._instances:
+                return (difference(self._qualifiers, other._qualifiers) or
+                        difference(other._qualifiers, self._qualifiers))
+            else:
+               self_set = identity.multiintersection(self._listSets(self))
+               other_set = identity.multiintersection(self._listSets(other))
+               return self_set != other_set
+        else:
+            self_set = identity.multiintersection(self._listSets(self))
+            return self_set != other
+                         
+    ## Helper Methods ##
+           
+    def _listSets(self, *extents):
+        """Return a list of identity sets that comprise extents"""
+        sets = []
+        for extent in extents:
+            for key in extent._qualifiers:
+                try:
+                    sets.append(self._instances[key])
+                except KeyError:
+                    pass # No instances for that type
+        return sets
+                        
 
 class ClassExtentMap(Persistent):
     """Object extents by class"""
@@ -40,7 +227,7 @@
     implements(IExtentMap)
     
     # Extent factory hook for testing/overriding
-    _extent_factory = ClassExtent
+    _extent_factory = Extent
     
     def __init__(self, dbconn):
         self._subclasses = OOBTree() # Map class key => set of subclass keys
@@ -55,7 +242,7 @@
             except KeyError:
                 raise KeyError, key
             else:
-                return self._extent_factory(key, subclass_keys, self._instances)
+                return self._extent_factory(subclass_keys, self._instances, key)
         else:
             raise TypeError, key
     




More information about the Zope-CVS mailing list