[Checkins] SVN: z3c.proxy/ - Implemented container location proxy and proxy aware

Roger Ineichen roger at projekt01.ch
Mon Jan 22 03:29:31 EST 2007


Log message for revision 72169:
  - Implemented container location proxy and proxy aware 
    object mover, copier and item renamer
  - Added unittests

Changed:
  A   z3c.proxy/branches/
  A   z3c.proxy/tags/
  A   z3c.proxy/trunk/
  A   z3c.proxy/trunk/src/
  A   z3c.proxy/trunk/src/z3c/
  A   z3c.proxy/trunk/src/z3c/proxy/
  A   z3c.proxy/trunk/src/z3c/proxy/README.txt
  A   z3c.proxy/trunk/src/z3c/proxy/SETUP.cfg
  A   z3c.proxy/trunk/src/z3c/proxy/__init__.py
  A   z3c.proxy/trunk/src/z3c/proxy/container.py
  A   z3c.proxy/trunk/src/z3c/proxy/interfaces.py
  A   z3c.proxy/trunk/src/z3c/proxy/overrides.zcml
  A   z3c.proxy/trunk/src/z3c/proxy/testing.py
  A   z3c.proxy/trunk/src/z3c/proxy/tests.py
  A   z3c.proxy/trunk/src/z3c/proxy/z3c.proxy-overrides.zcml

-=-
Added: z3c.proxy/trunk/src/z3c/proxy/README.txt
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/README.txt	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/README.txt	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,470 @@
+======
+README
+======
+
+We can proxy a regular container derived from zope's btree container for 
+example:
+
+  >>> from zope.app.container.interfaces import IContainer
+  >>> from zope.app.container.btree import BTreeContainer
+  >>> container = BTreeContainer()
+  >>> container.__name__, container.__parent__ = u'c1', u'p1'
+
+  >>> from z3c.proxy import interfaces
+  >>> from z3c.proxy.container import LocationProxy
+  >>> from z3c.proxy.container import ContainerLocationProxy
+  >>> proxy = ContainerLocationProxy(container)
+
+The name and the parent of the proxy is None. The proxy provides
+IContainer:
+
+  >>> proxy.__name__ is None
+  True
+  >>> proxy.__parent__ is None
+  True
+  >>> IContainer.providedBy(proxy)
+  True
+  >>> interfaces.IContainerLocationProxy.providedBy(proxy)
+  True
+
+First we check the empty proxy:
+
+  >>> proxy['x']
+  Traceback (most recent call last):
+  ...
+  KeyError: 'x'
+
+  >>> 'x' in proxy
+  False
+
+  >>> proxy.has_key('x')
+  0
+
+  >>> [key for key in proxy.keys()]
+  []
+
+  >>> [item for item in proxy.items()]
+  []
+
+  >>> proxy.get('x') is None
+  True
+
+  >>> iterator = iter(proxy)
+  >>> iterator.next()
+  Traceback (most recent call last):
+  ...
+  StopIteration
+
+  >>> proxy.values()
+  []
+
+  >>> len(proxy)
+  0
+
+  >>> del proxy['x']
+  Traceback (most recent call last):
+  ...
+  KeyError: 'x'
+
+  >>> from zope.app.container.contained import Contained
+  >>> proxy['x'] = x = Contained()
+
+Now we added our first item. This item should be added to the container.
+Its name will be x and its parent is the container itself:
+
+  >>> x is container['x']
+  True
+
+  >>> x.__name__
+  u'x'
+
+  >>> x.__parent__ is container
+  True
+
+If we lookup 'x' within the proxy we do not get the blank 'x' but rather
+the proxied 'x'. The proxy is not 'x' but only equal to 'x':
+
+  >>> x is proxy['x']
+  False
+
+  >>> x == proxy['x']
+  True
+
+  >>> x1 = proxy['x']
+  >>> from zope.proxy import isProxy
+  >>> isProxy(x1)
+  True
+
+  >>> isinstance(x1, LocationProxy)
+  True
+
+The proxied 'x' has still the same name but not the same parent:
+
+  >>> x1.__name__
+  u'x'
+
+  >>> x1.__parent__ is container
+  False
+
+  >>> x1.__parent__ is proxy
+  True
+
+If we add a second item to the container, it should appear in the
+proxy, too. But this item is proxied as container location proxy:
+
+  >>> container['y'] = y = BTreeContainer()
+  >>> y1 = proxy['y']
+  >>> y1 is y
+  False
+
+  >>> y1 == y
+  True
+
+  >>> isinstance(y1, ContainerLocationProxy)
+  True
+
+The container location proxy is able to proxy the location of
+nested objects:
+
+  >>> proxy['y']['z'] = z = Contained()
+  >>> container['y']['z'] is z
+  True
+
+  >>> z1 = y1['z']
+  >>> z1 is z
+  False
+
+  >>> z1 == z
+  True
+
+  >>> isinstance(z1, LocationProxy)
+  True
+
+  >>> z1.__parent__ is y1
+  True
+
+Finaly we check all other methods of the proxy:
+
+  >>> 'x' in proxy
+  True
+
+  >>> proxy.has_key('x')
+  1
+
+  >>> keys = [key for key in proxy.keys()]; keys.sort(); keys
+  [u'x', u'y']
+
+  >>> items = [item for item in proxy.items()]; items.sort()
+  >>> items == [(u'x', x), (u'y', y)]
+  True
+
+  >>> proxy.get('x') == x
+  True
+
+  >>> iterator = iter(proxy)
+  >>> iterator.next() in proxy
+  True
+
+  >>> iterator.next() in proxy
+  True
+
+  >>> iterator.next()     
+  Traceback (most recent call last):
+  ...
+  StopIteration
+
+  >>> values = proxy.values(); values.sort();
+  >>> x in values, y in values
+  (True, True)
+
+  >>> len(proxy)
+  2
+
+  >>> del proxy['x']
+  >>> 'x' in proxy
+  False
+
+
+ObjectMover
+-----------
+
+To use an object mover, pass a contained ``object`` to the class. The 
+contained ``object`` should implement ``IContained``.  It should be contained 
+in a container that has an adapter to ``INameChooser``.
+
+Setup test container and proxies:
+
+  >>> from zope.interface import implements
+  >>> from zope.app.container.interfaces import INameChooser
+  >>> from zope.copypastemove import ExampleContainer
+  >>> from z3c.proxy.container import ProxyAwareObjectMover
+  
+  >>> class ContainerLocationProxyStub(ContainerLocationProxy):
+  ... 
+  ...     implements(INameChooser)
+  ... 
+  ...     def chooseName(self, name, ob):
+  ...        while name in self:
+  ...            name += '_'
+  ...        return name
+
+  >>> container = ExampleContainer()
+  >>> container2 = ExampleContainer()
+
+  >>> ob = Contained()
+  >>> proxy = ContainerLocationProxyStub(container)
+  >>> proxy[u'foo'] = ob
+  >>> ob = proxy[u'foo']
+  >>> mover = ProxyAwareObjectMover(ob)
+
+In addition to moving objects, object movers can tell you if the object is 
+movable:
+
+  >>> mover.moveable()
+  1
+
+which, at least for now, they always are.  A better question to ask is whether 
+we can move to a particular container. Right now, we can always move to a 
+container of the same class:
+
+  >>> proxy2 = ContainerLocationProxyStub(container2)
+  >>> mover.moveableTo(proxy2)
+  1
+
+  >>> mover.moveableTo({})
+  Traceback (most recent call last):
+  ...
+  TypeError: Container is not a valid Zope container.
+
+Of course, once we've decided we can move an object, we can use the mover to 
+do so:
+
+  >>> mover.moveTo(proxy2)
+  u'foo'
+
+  >>> list(proxy)
+  []
+
+  >>> list(proxy2)
+  [u'foo']
+
+  >>> ob = proxy2[u'foo']
+  >>> ob.__parent__ is proxy2
+  True
+
+We can also specify a name:
+
+  >>> mover.moveTo(proxy2, u'bar')
+  u'bar'
+
+  >>> list(proxy2)
+  [u'bar']
+
+  >>> ob = proxy2[u'bar']
+  >>> ob.__parent__ is proxy2
+  True
+
+  >>> ob.__name__
+  u'bar'
+
+But we may not use the same name given, if the name is already in use:
+
+  >>> proxy2[u'splat'] = 1
+  >>> mover.moveTo(proxy2, u'splat')
+  u'splat_'
+
+  >>> l = list(proxy2)
+  >>> l.sort()
+  >>> l
+  [u'splat', u'splat_']
+
+  >>> ob = proxy2[u'splat_']
+  >>> ob.__name__
+  u'splat_'
+
+If we try to move to an invalid container, we'll get an error:
+
+  >>> mover.moveTo({})
+  Traceback (most recent call last):
+  ...
+  TypeError: Container is not a valid Zope container.
+
+
+ObjectCopier
+------------
+
+To use an object copier, pass a contained ``object`` to the class. The 
+contained ``object`` should implement ``IContained``.  It should be contained 
+in a container that has an adapter to `INameChooser`.
+
+Setup test container and proxies:
+
+  >>> from z3c.proxy.container import ProxyAwareObjectCopier
+  >>> class ContainerLocationProxyStub(ContainerLocationProxy):
+  ... 
+  ...     implements(INameChooser)
+  ... 
+  ...     def chooseName(self, name, ob):
+  ...        while name in self:
+  ...            name += '_'
+  ...        return name
+
+
+  >>> container = ExampleContainer()
+  >>> container2 = ExampleContainer()
+
+  >>> proxy = ContainerLocationProxyStub(container)
+  >>> proxy[u'foo'] = ob = Contained()
+  >>> ob = proxy[u'foo']
+  >>> copier = ProxyAwareObjectCopier(ob)
+
+In addition to moving objects, object copiers can tell you if the object is 
+movable:
+
+  >>> copier.copyable()
+  1
+
+which, at least for now, they always are.  A better question to ask is whether 
+we can copy to a particular container. Right now, we can always copy to a 
+container of the same class:
+
+  >>> proxy2 = ContainerLocationProxyStub(container2)
+  >>> copier.copyableTo(proxy2)
+  1
+
+  >>> copier.copyableTo({})
+  Traceback (most recent call last):
+  ...
+  TypeError: Container is not a valid Zope container.
+
+Of course, once we've decided we can copy an object, we can use the copier to 
+do so:
+
+  >>> copier.copyTo(proxy2)
+  u'foo'
+
+  >>> list(proxy)
+  [u'foo']
+
+  >>> list(proxy2)
+  [u'foo']
+
+  >>> ob.__parent__ is proxy
+  1
+
+  >>> proxy2[u'foo'] is ob
+  0
+
+  >>> proxy2[u'foo'].__parent__ is proxy2
+  1
+
+  >>> proxy2[u'foo'].__name__
+  u'foo'
+
+We can also specify a name:
+
+  >>> copier.copyTo(proxy2, u'bar')
+  u'bar'
+
+  >>> l = list(proxy2)
+  >>> l.sort()
+  >>> l
+  [u'bar', u'foo']
+
+  >>> ob.__parent__ is proxy
+  1
+
+  >>> proxy2[u'bar'] is ob
+  0
+
+  >>> proxy2[u'bar'].__parent__ is proxy2
+  1
+
+  >>> proxy2[u'bar'].__name__
+  u'bar'
+
+But we may not use the same name given, if the name is already in use:
+
+  >>> copier.copyTo(proxy2, u'bar')
+  u'bar_'
+
+  >>> l = list(proxy2)
+  >>> l.sort()
+  >>> l
+  [u'bar', u'bar_', u'foo']
+
+  >>> proxy2[u'bar_'].__name__
+  u'bar_'
+
+
+If we try to copy to an invalid container, we'll get an error:
+
+  >>> copier.copyTo({})
+  Traceback (most recent call last):
+  ...
+  TypeError: Container is not a valid Zope container.
+
+
+ProxyAwareContainerItemRenamer
+------------------------------
+
+This adapter uses IObjectMover to move an item within the same container to 
+a different name. We need to first setup an adapter for IObjectMover:
+
+Setup test container and proxies:
+
+  >>> from zope.app.container.sample import SampleContainer
+  >>> from zope.copypastemove import ContainerItemRenamer
+  >>> from zope.copypastemove import IObjectMover
+  >>> from z3c.proxy.container import ProxyAwareContainerItemRenamer
+
+  >>> import zope.component
+  >>> from zope.app.container.interfaces import IContained
+  >>> zope.component.provideAdapter(ProxyAwareObjectMover, [IContained], 
+  ...     IObjectMover)
+  
+  >>> class ContainerLocationProxyStub(ContainerLocationProxy):
+  ... 
+  ...     implements(INameChooser)
+  ... 
+  ...     def chooseName(self, name, ob):
+  ...        while name in self:
+  ...            name += '_'
+  ...        return name
+
+To rename an item in a container, instantiate a ContainerItemRenamer with the 
+container:
+
+  >>> container = SampleContainer()
+  >>> proxy = ContainerLocationProxyStub(container)
+  >>> renamer = ProxyAwareContainerItemRenamer(container)
+
+For this example, we'll rename an item 'foo':
+
+  >>> from z3c.proxy.container import _unproxy
+  >>> foo = Contained()
+  >>> proxy['foo'] = foo
+  >>> proxy['foo'] == _unproxy(foo)
+  True
+
+to 'bar':
+
+  >>> renamer.renameItem('foo', 'bar')
+  >>> proxy['foo'] is foo
+  Traceback (most recent call last):
+  KeyError: 'foo'
+
+  >>> proxy['bar'] == _unproxy(foo)
+  True
+
+If the item being renamed isn't in the container, a NotFoundError is raised:
+
+  >>> renamer.renameItem('foo', 'bar') # doctest:+ELLIPSIS
+  Traceback (most recent call last):
+  ItemNotFoundError: (<...SampleContainer...>, 'foo')
+
+If the new item name already exists, a DuplicationError is raised:
+
+  >>> renamer.renameItem('bar', 'bar')
+  Traceback (most recent call last):
+  DuplicationError: bar is already in use


Property changes on: z3c.proxy/trunk/src/z3c/proxy/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/SETUP.cfg
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/SETUP.cfg	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/SETUP.cfg	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,3 @@
+<data-files zopeskel/etc/package-includes>
+  z3c.proxy-*.zcml
+</data-files>


Property changes on: z3c.proxy/trunk/src/z3c/proxy/SETUP.cfg
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/__init__.py
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/__init__.py	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/__init__.py	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,16 @@
+###############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+###############################################################################
+"""
+$Id$
+"""


Property changes on: z3c.proxy/trunk/src/z3c/proxy/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/container.py
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/container.py	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/container.py	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,125 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+##############################################################################
+"""
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.interface import implements
+from zope.copypastemove import ObjectCopier
+from zope.copypastemove import ObjectMover
+from zope.copypastemove import ContainerItemRenamer
+from zope.location import LocationProxy
+from zope.proxy import getProxiedObject
+from zope.proxy import non_overridable
+from zope.proxy import isProxy
+
+from zope.app.container.interfaces import IContainer
+from z3c.proxy import interfaces
+
+
+def proxify(container, item):
+    if IContainer.providedBy(item):
+        proxy = ContainerLocationProxy(item)
+    else:
+        proxy = LocationProxy(item)
+    proxy.__name__ = item.__name__
+    proxy.__parent__ = container
+    return proxy
+
+
+def _unproxy(obj):
+    # precondition: treate only proxied objects
+    if not isProxy(obj):
+        return obj
+    # essential
+    return getProxiedObject(obj)
+
+
+class ContainerLocationProxy(LocationProxy):
+    """Proxy the location of a container an its items."""
+
+    implements(interfaces.IContainerLocationProxy)
+
+    # zope.app.conatiner.interfaces.IReadContainer
+    @non_overridable
+    def __getitem__(self, key):
+        return proxify(self, getProxiedObject(self).__getitem__(key))
+
+    @non_overridable
+    def __contains__(self, key):
+        return getProxiedObject(self).__contains__(key)
+
+    @non_overridable
+    def has_key(self, key):
+        return getProxiedObject(self).has_key(key)
+
+    @non_overridable
+    def keys(self):
+        return getProxiedObject(self).keys()
+
+    @non_overridable
+    def items(self):
+        return [(key, proxify(self, item)) for key, item in getProxiedObject(self).items()]
+
+    @non_overridable
+    def get(self, key, default=None):
+        item = getProxiedObject(self).get(key, default)
+
+        if item is not default:
+            return proxify(self, item)
+
+        else:
+            return default
+
+    @non_overridable
+    def __iter__(self):
+        return iter(getProxiedObject(self))
+
+    @non_overridable
+    def values(self):
+        return [proxify(self, value) for value in getProxiedObject(self).values()]
+
+    @non_overridable
+    def __len__(self):
+        return getProxiedObject(self).__len__()
+
+    # zope.app.conatiner.interfaces.IWriteContainer
+    @non_overridable
+    def __delitem__(self, key):
+        getProxiedObject(self).__delitem__(key)
+
+    @non_overridable
+    def __setitem__(self, key, value):
+        getProxiedObject(self).__setitem__(key, value)
+
+
+class ProxyAwareObjectMover(ObjectMover):
+    """Adapter for moving objects between containers that removes proxies."""
+    def __init__(self, object):
+        super(ProxyAwareObjectMover, self).__init__(_unproxy(object))
+
+
+class ProxyAwareObjectCopier(ObjectCopier):
+    """Adapter for copying objects between containers that removes proxies."""
+    def __init__(self, object):
+        super(ProxyAwareObjectCopier, self).__init__(_unproxy(object))
+
+
+class ProxyAwareContainerItemRenamer(ContainerItemRenamer):
+    """An IContainerItemRenamer adapter for containers."""
+    def __init__(self, container):
+        super(ProxyAwareContainerItemRenamer, self).__init__(
+            _unproxy(container))
+


Property changes on: z3c.proxy/trunk/src/z3c/proxy/container.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/interfaces.py
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/interfaces.py	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/interfaces.py	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,26 @@
+###############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+###############################################################################
+"""
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+
+from zope.location.interfaces import ILocation
+from zope.app.container.interfaces import IContainer
+
+
+
+class IContainerLocationProxy(ILocation, IContainer):
+    """Container proxy supporting a location."""
\ No newline at end of file


Property changes on: z3c.proxy/trunk/src/z3c/proxy/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/overrides.zcml
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/overrides.zcml	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/overrides.zcml	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,38 @@
+<configure 
+    xmlns="http://namespaces.zope.org/zope"
+    i18n_domain="z3c">
+
+  <!-- TODO: This adapter should be regsitred to the the LocationProxy class
+       and not use overrides.zcml. But this doesn't work. Find a way where we 
+       can register this adapters without overrides.zcml. -->
+
+  <!-- support move for LocationProxy items -->
+  <adapter
+      factory="z3c.proxy.adapters.ProxyAwareObjectMover"
+      provides="zope.copypastemove.interfaces.IObjectMover"
+      permission="zope.ManageContent"
+      for="zope.app.container.interfaces.IContained"
+      trusted="True"
+      />
+
+
+  <!-- support copy/paste for LocationProxy items -->
+  <adapter
+      factory="z3c.proxy.adapters.ProxyAwareObjectCopier"
+      provides="zope.copypastemove.interfaces.IObjectCopier"
+      permission="zope.ManageContent"
+      for="zope.app.container.interfaces.IContained"
+      trusted="True"
+      />
+
+
+  <!-- support rename for ContainerLocationProxy items -->
+  <adapter
+      factory="z3c.proxy.adapters.ProxyAwareContainerItemRenamer"
+      provides="zope.copypastemove.interfaces.IContainerItemRenamer"
+      permission="zope.ManageContent"
+      for="zope.app.container.interfaces.IContainer"
+      trusted="True"
+      />
+
+</configure>
\ No newline at end of file


Property changes on: z3c.proxy/trunk/src/z3c/proxy/overrides.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/testing.py
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/testing.py	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/testing.py	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,56 @@
+###############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+###############################################################################
+"""
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import zope.interface
+from zope.app.container.interfaces import IContainer
+from zope.app.container.tests.test_icontainer import BaseTestIContainer as BT
+from zope.app.container.tests.test_icontainer import DefaultTestData
+
+from z3c.testing.app import InterfaceBaseTest
+from z3c.proxy import interfaces
+from z3c.proxy import container
+
+
+# stub testing classes
+class ISampleContainerProxy(IContainer):
+    """Sample interface."""
+
+
+class SampleContainerProxy(container.ContainerLocationProxy):
+    """Sample implementation."""
+
+    zope.interface.implements(ISampleContainerProxy)
+
+
+class BaseTestIContainerLocationProxy(InterfaceBaseTest, BT):
+
+    def getTestInterface(self):
+        return interfaces.IContainerLocationProxy
+
+    def makeTestData(self):
+        return DefaultTestData()
+
+    def getUnknownKey(self):
+        return '10'
+
+    def getBadKeyTypes(self):
+        return [None, ['foo'], 1, '\xf3abc']
+
+    def test_IContainer(self):
+        proxy = self.makeTestObject()
+        self.assertEqual(IContainer.providedBy(proxy), True)


Property changes on: z3c.proxy/trunk/src/z3c/proxy/testing.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/tests.py
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/tests.py	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/tests.py	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,50 @@
+###############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+###############################################################################
+"""
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+from zope.testing.doctestunit import DocTestSuite
+from zope.testing.doctestunit import DocFileSuite
+from zope.app.container.sample import SampleContainer
+from zope.app.testing.placelesssetup import setUp
+from zope.app.testing.placelesssetup import tearDown
+
+from z3c.proxy import testing
+
+
+class SampleContainerTest(testing.BaseTestIContainerLocationProxy):
+    """Base container test sample."""
+
+    def getTestInterface(self):
+        return testing.ISampleContainerProxy
+
+    def getTestClass(self):
+        return testing.SampleContainerProxy 
+
+    def makeTestObject(self):
+        obj = SampleContainer()
+        return testing.SampleContainerProxy(obj)
+
+
+def test_suite():
+    return unittest.TestSuite((
+        DocFileSuite('README.txt',
+                     setUp=setUp, tearDown=tearDown),
+        unittest.makeSuite(SampleContainerTest),
+        ))
+
+if __name__ == '__main__': unittest.main(SampleContainerTest)


Property changes on: z3c.proxy/trunk/src/z3c/proxy/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: z3c.proxy/trunk/src/z3c/proxy/z3c.proxy-overrides.zcml
===================================================================
--- z3c.proxy/trunk/src/z3c/proxy/z3c.proxy-overrides.zcml	2007-01-22 08:25:30 UTC (rev 72168)
+++ z3c.proxy/trunk/src/z3c/proxy/z3c.proxy-overrides.zcml	2007-01-22 08:29:30 UTC (rev 72169)
@@ -0,0 +1,5 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+  <include package="z3c.proxy" file="overrides.zcml" />
+
+</configure>
\ No newline at end of file


Property changes on: z3c.proxy/trunk/src/z3c/proxy/z3c.proxy-overrides.zcml
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list