[Zope-CVS] SVN: Sandbox/zc/extrinsicreference/ Making a snapshot available for evaluation.

Jim Fulton jim at zope.com
Sat Nov 12 11:06:49 EST 2005


Log message for revision 40056:
  Making a snapshot available for evaluation.
  

Changed:
  A   Sandbox/zc/extrinsicreference/
  A   Sandbox/zc/extrinsicreference/__init__.py
  A   Sandbox/zc/extrinsicreference/configure.zcml
  A   Sandbox/zc/extrinsicreference/extrinsicreference.py
  A   Sandbox/zc/extrinsicreference/extrinsicreference.txt
  A   Sandbox/zc/extrinsicreference/interfaces.py
  A   Sandbox/zc/extrinsicreference/tests.py
  A   Sandbox/zc/extrinsicreference/track_shortcuts.zcml

-=-
Added: Sandbox/zc/extrinsicreference/__init__.py
===================================================================
--- Sandbox/zc/extrinsicreference/__init__.py	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/__init__.py	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1 @@
+from extrinsicreference import *


Property changes on: Sandbox/zc/extrinsicreference/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/configure.zcml
===================================================================
--- Sandbox/zc/extrinsicreference/configure.zcml	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/configure.zcml	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,18 @@
+<configure
+        xmlns='http://namespaces.zope.org/zope'
+        xmlns:browser='http://namespaces.zope.org/browser'
+        i18n_domain="zc.intranet">
+
+    <content class=".extrinsicreference.ExtrinsicReferences">
+        <implements
+            interface="zope.app.annotation.interfaces.IAttributeAnnotatable"/>
+        <implements interface="zope.app.utility.interfaces.ILocalUtility"/>
+    </content>
+
+    <browser:addMenuItem
+            class=".extrinsicreference.ExtrinsicReferences"
+            title="Extrinsic References"
+            permission= "zope.ManageContent"
+    />
+
+</configure>


Property changes on: Sandbox/zc/extrinsicreference/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/extrinsicreference.py
===================================================================
--- Sandbox/zc/extrinsicreference/extrinsicreference.py	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/extrinsicreference.py	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL 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.
+#
+##############################################################################
+"""extrinsic references
+
+$Id$
+"""
+import persistent
+from BTrees import OOBTree
+
+from zope import interface
+from zope.app.keyreference.interfaces import IKeyReference
+from zope.app.component.interfaces import ILocalUtility
+
+from zc.extrinsicreference.interfaces import IExtrinsicReferences
+
+class ExtrinsicReferences(persistent.Persistent):
+
+    interface.implements(IExtrinsicReferences, ILocalUtility)
+
+    # To be usable as an ILocalUtility we have to have these.
+    __parent__ = __name__ = None
+
+    def __init__(self):
+        self.references = OOBTree.OOBTree()
+
+    def add(self, obj, value):
+        key = IKeyReference(obj)
+        refs = self.references.get(key)
+        if refs is None:
+            refs = self.references[key] = OOBTree.OOTreeSet()
+        refs.insert(IKeyReference(value))
+
+    def update(self, obj, values):
+        key = IKeyReference(obj)
+        refs = self.references.get(key)
+        if refs is None:
+            refs = self.references[key] = OOBTree.OOTreeSet()
+        refs.update(IKeyReference(v) for v in values)
+
+    def remove(self, obj, value):
+        key = IKeyReference(obj)
+        refs = self.references.get(key)
+        if refs is not None:
+            refs.remove(IKeyReference(value)) # raises KeyError when we desire
+        else:
+            raise KeyError("Object and value pair does not exist")
+
+    def discard(self, obj, value):
+        try:
+            self.remove(obj, value)
+        except KeyError:
+            pass
+
+    def contains(self, obj, value):
+        key = IKeyReference(obj)
+        refs = self.references.get(key)
+        if refs is not None:
+            return IKeyReference(value) in refs
+        return False
+
+    def set(self, obj, values):
+        key = IKeyReference(obj)
+        refs = self.references.get(key)
+        vals = [IKeyReference(v) for v in values]
+        if not vals:
+            if refs is not None:
+                # del
+                del self.references[key]
+        else:
+            if refs is None:
+                refs = self.references[key] = OOBTree.OOTreeSet()
+            else:
+                refs.clear()
+            refs.update(vals)
+
+    def get(self, obj):
+        key = IKeyReference(obj)
+        refs = self.references.get(key, ())
+        for kr in refs:
+            yield kr()
+
+# TODO these belong elsewhere (zc.shortcut, maybe?)
+from zope import component
+from zc.shortcut.interfaces import IShortcut
+
+def registerShortcut(shortcut, event):
+    """Subscriber to add an extrinsic reference."""
+    registry = component.queryUtility(IExtrinsicReferences, 'shortcuts')
+    if registry is not None:
+        # We use raw_target because we don't want a proxy.
+        registry.add(shortcut.raw_target, shortcut)
+
+def unregisterShortcut(shortcut, event):
+    """Subscriber to remove an extrinsic reference."""
+    registry = component.queryUtility(IExtrinsicReferences, 'shortcuts')
+    if registry is not None:
+        # We use raw_target because we don't want a proxy.
+        registry.discard(shortcut.raw_target, shortcut)


Property changes on: Sandbox/zc/extrinsicreference/extrinsicreference.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/extrinsicreference.txt
===================================================================
--- Sandbox/zc/extrinsicreference/extrinsicreference.txt	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/extrinsicreference.txt	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,136 @@
+====================
+Extrinsic References
+====================
+
+Extrinsic registries record a key and one or more values to which they
+refer.  The key and all values must be adaptable to 
+zope.app.keyreference.interfaces.IKeyReference.
+
+    >>> from zc.extrinsicreference import ExtrinsicReferences
+    >>> references = ExtrinsicReferences()
+    >>> references.add(1, 2)
+    Traceback (most recent call last):
+    ...
+    TypeError: ('Could not adapt', 1...
+    >>> from zope import interface, component
+    >>> from zope.app.keyreference.interfaces import IKeyReference
+    >>> class IMyObject(interface.Interface):
+    ...     "An interface for which we register an IKeyReference adapter"
+    ...     id = interface.Attribute("An id unique to IMyObject instances")
+    ...
+    >>> class MyObject(object):
+    ...     interface.implements(IMyObject)
+    ...     _id_counter  = 0
+    ...     @classmethod
+    ...     def _getId(cls):
+    ...         val = cls._id_counter
+    ...         cls._id_counter += 1
+    ...         return val
+    ...     def __init__(self):
+    ...         self.id = self._getId()
+    ...
+    >>> class DummyKeyReference(object):
+    ...     interface.implements(IKeyReference)
+    ...     component.adapts(IMyObject)
+    ...     key_type_id = 'zc.extrinsicreference.doctest'
+    ...     def __init__(self, obj):
+    ...         self.object = obj
+    ...     def __call__(self):
+    ...         """Get the object this reference is linking to.
+    ...         """
+    ...         return self.object
+    ...     def __hash__(self):
+    ...         """Get a unique identifier of the referenced object.
+    ...         """
+    ...         return hash(self.object.id)
+    ...     def __cmp__(self, other):
+    ...         """Compare the reference to another reference.
+    ...         """
+    ...         if self.key_type_id == other.key_type_id:
+    ...             return cmp(self.object.id, other.object.id)
+    ...         return cmp(self.key_type_id, other.key_type_id)
+    ...
+    >>> component.provideAdapter(DummyKeyReference)
+    >>> object1 = MyObject()
+    >>> references.add(object1, 2)
+    Traceback (most recent call last):
+    ...
+    TypeError: ('Could not adapt', 2...
+    >>> value1 = MyObject()
+    >>> value2 = MyObject()
+    >>> references.add(object1, value1)
+    >>> references.add(object1, value2)
+
+Values can be retrieved by their key:
+
+    >>> set(references.get(object1)) == set((value1, value2))
+    True
+
+References can be removed:
+
+    >>> references.remove(object1, value1)
+    >>> list(references.get(object1)) == [value2]
+    True
+
+But if the reference is not registered, removing it raises a KeyError.
+
+    >>> references.remove(object1, value1)
+    Traceback (most recent call last):
+    ...
+    KeyError:...
+    >>> object2 = MyObject()
+    >>> references.remove(object2, value2)
+    Traceback (most recent call last):
+    ...
+    KeyError:...
+
+If you prefer to silently ignore these errors, use `discard`.
+
+    >>> references.discard(object1, value1)
+    >>> references.discard(object2, value2)
+
+Otherwise, you can use `contains` to determine if the reference exists:
+
+    >>> references.contains(object1, value1)
+    False
+    >>> references.contains(object2, value2)
+    False
+    >>> references.contains(object1, value2)
+    True
+
+If a key has no associated values, an empty iterable is returned:
+
+    >>> references.discard(object1, value2)
+    >>> list(references.get(object1))
+    []
+
+Adding a value more than once does not cause the value to be included
+in the result sequence more than once:
+
+    >>> references.add(object1, value1)
+    >>> references.add(object1, value1)
+    >>> list(references.get(object1)) == [value1]
+    True
+
+The `set` method destructively sets the given values for the object.  Repeated
+objects are collapsed to a single instance.
+
+    >>> references.set(object1, (value2, object2, value2, value2, object2))
+    >>> references.contains(object1, value1)
+    False
+    >>> len(list(references.get(object1)))
+    2
+    >>> set(references.get(object1)) == set((value2, object2))
+    True
+    >>> references.set(object1, ())
+    >>> len(list(references.get(object1)))
+    0
+
+The `update` method adds values to the previous values, non-destructively.
+
+    >>> references.add(object1, value1)
+    >>> references.update(object1, (value2, object2, value2))
+    >>> len(list(references.get(object1)))
+    3
+    >>> set(references.get(object1)) == set((value1, value2, object2))
+    True


Property changes on: Sandbox/zc/extrinsicreference/extrinsicreference.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/interfaces.py
===================================================================
--- Sandbox/zc/extrinsicreference/interfaces.py	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/interfaces.py	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,81 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL 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 zope import interface
+import zope.app.location
+
+
+class IExtrinsicReferences(interface.Interface):
+    """An object that stores extrinsic references to another object
+
+    All objects must be adaptable to 
+    zope.app.keyreference.interfaces.IKeyReference."""
+
+    def add(obj, value):
+        """Add an object and an associated value to the registry.
+        
+        Both object and value must be adaptable to IKeyReference.
+
+        Multiple values may be stored for a single key.  Each value is
+        only stored once; comparisons are performed using the value's
+        IKeyReference hash.
+        """
+
+    def update(obj, values):
+        """For given object, add all values in iterable values.
+
+        Object and each value must be adaptable to IKeyReference.  Identical
+        values (as determined by IKeyReference) are collapsed to a single
+        instance (so, for instance, a set of [A, B, B, C, B] will be
+        collapsed to a logical set of A, B, C).
+        """
+
+    def get(obj):
+        """Retrieve an iterable of the values associated with the object.
+
+        If there are no references for `obj`, an iterable with no entries is
+        returned.
+        """
+
+    def remove(obj, value):
+        """Remove the specified value associated with the object.
+
+        Comparisons are made with the IKeyReference hashes.
+
+        If `value` is not set for `obj`, raises KeyError.
+        """
+
+    def contains(obj, value):
+        """returns a boolean value of whether the obj : value pair exists."""
+
+    def discard(obj, value):
+        """Remove the specified value associated with the object.
+
+        Comparisons are made with the IKeyReference hashes.
+
+        If `value` is not set for `obj`, silently ignores.
+        """
+
+    def set(obj, values):
+        """Set the values for obj to the values in the given iterable.
+
+        Replaces any previous values for obj.  Object and each value must be 
+        adaptable to IKeyReference.  Identical values (as determined by
+        IKeyReference) are collapsed to a single instance (so, for instance,
+        values of [A, B, B, C, B] will be collapsed to a logical set of 
+        A, B, C).
+
+        Setting an empty values is the canonical way of clearing values for an
+        object.
+        """


Property changes on: Sandbox/zc/extrinsicreference/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/tests.py
===================================================================
--- Sandbox/zc/extrinsicreference/tests.py	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/tests.py	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Visible Source
+# License, Version 1.0 (ZVSL).  A copy of the ZVSL 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.
+#
+##############################################################################
+"""extrinsicreference module test runner
+
+$Id$
+"""
+import unittest
+
+from zope.testing import doctest
+from zope.app.tests import placelesssetup
+
+def test_suite():
+    return doctest.DocFileSuite(
+        'extrinsicreference.txt',
+        setUp=placelesssetup.setUp, tearDown=placelesssetup.tearDown,
+        optionflags=doctest.ELLIPSIS)
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: Sandbox/zc/extrinsicreference/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: Sandbox/zc/extrinsicreference/track_shortcuts.zcml
===================================================================
--- Sandbox/zc/extrinsicreference/track_shortcuts.zcml	2005-11-12 15:12:35 UTC (rev 40055)
+++ Sandbox/zc/extrinsicreference/track_shortcuts.zcml	2005-11-12 16:06:49 UTC (rev 40056)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configure xmlns="http://namespaces.zope.org/zope">
+
+    <subscriber
+        for="zc.shortcut.interfaces.IShortcut
+             zope.app.container.interfaces.IObjectAddedEvent"
+        handler="zc.extrinsicreference.registerShortcut"
+        />
+
+    <subscriber
+        for="zc.shortcut.interfaces.IShortcut
+             zope.app.container.interfaces.IObjectRemovedEvent"
+        handler="zc.extrinsicreference.unregisterShortcut"
+        />
+
+</configure>


Property changes on: Sandbox/zc/extrinsicreference/track_shortcuts.zcml
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Zope-CVS mailing list