[Checkins] SVN: Sandbox/malthe/zope.container/ Initial package creation.

Malthe Borch mborch at gmail.com
Tue Apr 22 08:37:09 EDT 2008


Log message for revision 85592:
  Initial package creation.

Changed:
  U   Sandbox/malthe/zope.container/CHANGES.txt
  U   Sandbox/malthe/zope.container/README.txt
  U   Sandbox/malthe/zope.container/buildout.cfg
  D   Sandbox/malthe/zope.container/include/
  U   Sandbox/malthe/zope.container/setup.py
  D   Sandbox/malthe/zope.container/src/zope/app/
  A   Sandbox/malthe/zope.container/src/zope/container/
  A   Sandbox/malthe/zope.container/src/zope/container/__init__.py
  A   Sandbox/malthe/zope.container/src/zope/container/constraints.py
  A   Sandbox/malthe/zope.container/src/zope/container/constraints.txt
  A   Sandbox/malthe/zope.container/src/zope/container/find.py
  A   Sandbox/malthe/zope.container/src/zope/container/i18n.py
  A   Sandbox/malthe/zope.container/src/zope/container/interfaces.py
  A   Sandbox/malthe/zope.container/src/zope/container/property.py
  A   Sandbox/malthe/zope.container/src/zope/container/property.txt
  A   Sandbox/malthe/zope.container/src/zope/container/size.py
  A   Sandbox/malthe/zope.container/src/zope/container/tests/
  D   Sandbox/malthe/zope.container/src/zope/container/tests/placelesssetup.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_btree.py
  U   Sandbox/malthe/zope.container/src/zope/container/tests/test_constraints.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_contained.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraversable.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraverser.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_dependency.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_directory.py
  U   Sandbox/malthe/zope.container/src/zope/container/tests/test_find.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_icontainer.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_objectcopier.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_objectmover.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_ordered.py
  A   Sandbox/malthe/zope.container/src/zope/container/tests/test_property.py
  U   Sandbox/malthe/zope.container/src/zope/container/tests/test_size.py
  D   Sandbox/malthe/zope.container/src/zope/container/tests/test_view_permissions.py

-=-
Modified: Sandbox/malthe/zope.container/CHANGES.txt
===================================================================
--- Sandbox/malthe/zope.container/CHANGES.txt	2008-04-22 12:19:47 UTC (rev 85591)
+++ Sandbox/malthe/zope.container/CHANGES.txt	2008-04-22 12:37:09 UTC (rev 85592)
@@ -5,46 +5,5 @@
 3.6.0 (unreleased)
 ------------------
 
-- Added an ``IBTreeContainer`` interface that allows an argument to the
-  ``items``, ``keys``, and ``values`` methods with the same semantics as for
-  a BTree object.  The extended interface is implemented by the
-  ``BTreeContainer`` class.
-
-3.5.3 (2007-11-09)
-------------------
-
-- Send ``IObjectModifiedEvent`` when changing the title through the
-  ``@@contents.html`` view.
-
-  This fixes https://bugs.edge.launchpad.net/zope3/+bug/98483.
-
-3.5.2 (2007-11-01)
-------------------
-
-- Reactivated functional tests.
-
-3.5.1 (2007-10-31)
-------------------
-
-- Resolve ``ZopeSecurityPolicy`` and ``IRolePermissionManager`` deprecation
-  warning.
-
-3.5.0 (2007-10-11)
-------------------
-
-- Updated package meta-data.
-
-3.5.0a1 (2007-06-29)
---------------------
-
-* Updated bootstrap script to current version.
-
-* Store length of ``BTreeContainer`` in its own ``Length`` object for faster
-  ``__len__`` implementation of huge containers.
-
-
-3.4.0a1 (2007-04-22)
---------------------
-
-- Initial release as a separate project, corresponds to ``zope.app.container``
-  from Zope 3.4.0a1.
+- Initial creation of package based on parts in ``zope.app.container``
+  that do not depend on the ZODB.

Modified: Sandbox/malthe/zope.container/README.txt
===================================================================
--- Sandbox/malthe/zope.container/README.txt	2008-04-22 12:19:47 UTC (rev 85591)
+++ Sandbox/malthe/zope.container/README.txt	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,3 +1,2 @@
-This package define interfaces of container components, and provides
-sample container implementations such as a BTreeContainer and
-OrderedContainer.
+This package define interfaces of container components and implements
+container constraints and utilities.

Modified: Sandbox/malthe/zope.container/buildout.cfg
===================================================================
--- Sandbox/malthe/zope.container/buildout.cfg	2008-04-22 12:19:47 UTC (rev 85591)
+++ Sandbox/malthe/zope.container/buildout.cfg	2008-04-22 12:37:09 UTC (rev 85592)
@@ -4,5 +4,5 @@
 
 [test]
 recipe = zc.recipe.testrunner
-eggs = zope.app.container [test]
+eggs = zope.container
 

Modified: Sandbox/malthe/zope.container/setup.py
===================================================================
--- Sandbox/malthe/zope.container/setup.py	2008-04-22 12:19:47 UTC (rev 85591)
+++ Sandbox/malthe/zope.container/setup.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2006 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Setup for zope.app.container package
+"""Setup for zope.container package
 
 $Id$
 """
@@ -21,7 +21,7 @@
 def read(*rnames):
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
-setup(name='zope.app.container',
+setup(name='zope.container',
       version = '3.6.0',
       author='Zope Corporation and Contributors',
       author_email='zope3-dev at zope.org',
@@ -32,7 +32,7 @@
           'Detailed Documentation\n'
           '**********************\n'
           + '\n\n' +
-          read('src', 'zope', 'app', 'container', 'constraints.txt')
+          read('src', 'zope', 'container', 'constraints.txt')
           + '\n\n' +
           read('CHANGES.txt')
           ),
@@ -47,43 +47,19 @@
           'Operating System :: OS Independent',
           'Topic :: Internet :: WWW/HTTP',
           'Framework :: Zope3'],
-      url='http://cheeseshop.python.org/pypi/zope.app.container',
+      url='http://cheeseshop.python.org/pypi/zope.container',
       license='ZPL 2.1',
       packages=find_packages('src'),
       package_dir = {'': 'src'},
-      namespace_packages=['zope', 'zope.app'],
-      ext_modules=[Extension("zope.app.container._zope_app_container_contained",
-                             [os.path.join("src", "zope", "app", "container",
-                                           "_zope_app_container_contained.c")
-                              ], include_dirs=['include']),
-                   ],
-
-      extras_require=dict(test=['zope.app.testing',
-                                'zope.app.securitypolicy',
-                                'zope.app.zcmlfiles',
-                                'zope.app.file']),
+      namespace_packages=['zope', ],
       install_requires=['setuptools',
                         'zope.interface',
-                        'zope.deprecation',
-                        'zope.app.publisher',
-                        'zope.cachedescriptors',
-                        'zope.dottedname',
-                        'zope.schema',
                         'zope.component',
-                        'zope.event',
+                        'zope.size',
+                        'zope.dottedname',
                         'zope.location',
-                        'zope.exceptions',
-                        'zope.security',
                         'zope.lifecycleevent',
-                        'zope.i18nmessageid',
-                        'zope.filerepresentation',
-                        'zope.size',
-                        'zope.traversing',
-                        'zope.publisher',
-                        'zope.dublincore',
-                        'zope.app.broken',
-                        'zope.copypastemove',
-                        'ZODB3',
+                        'zope.deprecation',
                         ],
       include_package_data = True,
       zip_safe = False,

Copied: Sandbox/malthe/zope.container/src/zope/container/__init__.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/__init__.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/__init__.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/__init__.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.

Copied: Sandbox/malthe/zope.container/src/zope/container/constraints.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/constraints.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/constraints.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/constraints.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,461 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Support for containment constraints
+
+   Either a container or an object can provide constraints on the
+   containment relationship.
+
+   A container expresses constraints through a precondition on it's
+   `__setitem__` method in it's interface.
+
+   Preconditions can be simple callable objects, like functions. They
+   should raise a ``zope.interface.Invalid`` exception to indicate that a
+   constraint isn't satisfied:
+
+   >>> def preNoZ(container, name, ob):
+   ...     "Silly precondition example"
+   ...     if name.startswith("Z"):
+   ...         raise zope.interface.Invalid("Names can not start with Z")
+
+   >>> class I1(zope.interface.Interface):
+   ...     def __setitem__(name, on):
+   ...         "Add an item"
+   ...     __setitem__.precondition = preNoZ
+
+   >>> from zope.container.interfaces import IContainer
+   >>> class C1(object):
+   ...     zope.interface.implements(I1, IContainer)
+   ...     def __repr__(self):
+   ...         return 'C1'
+
+   Given such a precondition, we can then check whether an object can be
+   added:
+
+   >>> c1 = C1()
+   >>> checkObject(c1, "bob", None)
+   >>> checkObject(c1, "Zbob", None)
+   Traceback (most recent call last):
+   ...
+   Invalid: Names can not start with Z
+
+   We can also express constaints on the containers an object can be
+   added to. We do this by setting a field constraint on an object's
+   `__parent__` attribute:
+
+   >>> import zope.schema
+
+   A field constraint is a callable object that returns a boolean value:
+
+   >>> def con1(container):
+   ...     "silly container constraint"
+   ...     if not hasattr(container, 'x'):
+   ...         return False
+   ...     return True
+
+   >>> class I2(zope.interface.Interface):
+   ...     __parent__ = zope.schema.Field(constraint = con1)
+
+   >>> class O(object):
+   ...     zope.interface.implements(I2)
+
+   If the constraint isn't satisfied, we'll get a validation error when we
+   check whether the object can be added:
+
+   >>> checkObject(c1, "bob", O())
+   Traceback (most recent call last):
+   ...
+   ConstraintNotSatisfied: C1
+
+   Note that the validation error isn't very informative. For that
+   reason, it's better for constraints to raise Invalid errors when they
+   aren't satisfied:
+
+   >>> def con1(container):
+   ...     "silly container constraint"
+   ...     if not hasattr(container, 'x'):
+   ...         raise zope.interface.Invalid("What, no x?")
+   ...     return True
+
+   >>> class I2(zope.interface.Interface):
+   ...     __parent__ = zope.schema.Field(constraint = con1)
+
+   >>> class O(object):
+   ...     zope.interface.implements(I2)
+
+   >>> checkObject(c1, "bob", O())
+   Traceback (most recent call last):
+   ...
+   Invalid: What, no x?
+
+   >>> c1.x = 1
+   >>> checkObject(c1, "bob", O())
+
+   The `checkObject` function is handy when checking whether we can add an
+   existing object to a container, but, sometimes, we want to check
+   whether an object produced by a factory can be added.  To do this, we
+   use `checkFactory`:
+
+   >>> class Factory(object):
+   ...     def __call__(self):
+   ...         return O()
+   ...     def getInterfaces(self):
+   ...         return zope.interface.implementedBy(O)
+
+   >>> factory = Factory()
+
+   >>> checkFactory(c1, "bob", factory)
+   True
+
+   >>> del c1.x
+   >>> checkFactory(c1, "bob", factory)
+   False
+
+   Unlike `checkObject`, `checkFactory`:
+
+   - Returns a boolean value
+
+   - Takes a factory (e.g. a class) rather than an argument.
+
+   The container constraint we defined for C1 isn't actually used to
+   check the factory:
+
+   >>> c1.x = 1
+   >>> checkFactory(c1, "Zbob", factory)
+   True
+
+   To work with `checkFactory`, a container precondition has to
+   implement a factory method.  This is because a factory, rather than
+   an object is passed.  To illustrate this, we'll make preNoZ its own
+   factory method:
+
+   >>> preNoZ.factory = preNoZ
+
+   We can do this (silly thing) because preNoZ doesn't use the object
+   argument.
+
+   >>> checkFactory(c1, "Zbob", factory)
+   False
+
+   $Id$
+   """
+__docformat__ = 'restructuredtext'
+
+import sys
+
+from zope.container.property import readproperty
+from zope.dottedname.resolve import resolve
+import zope.schema
+from zope.interface import providedBy
+from zope.container.interfaces import InvalidItemType, InvalidContainerType
+from zope.container.i18n import ZopeMessageFactory as _
+from zope.container.interfaces import IContainer
+
+def checkObject(container, name, object):
+    """Check containement constraints for an object and container
+    """
+
+    # check __setitem__ precondition
+    containerProvided = providedBy(container)
+    __setitem__ = containerProvided.get('__setitem__')
+    if __setitem__ is not None:
+        precondition = __setitem__.queryTaggedValue('precondition')
+        if precondition is not None:
+            precondition(container, name, object)
+
+    # check the constraint on __parent__
+    __parent__ = providedBy(object).get('__parent__')
+    if __parent__ is not None:
+        try:
+            validate = __parent__.validate
+        except AttributeError:
+            pass
+        else:
+            validate(container)
+
+
+    if not containerProvided.extends(IContainer):
+        # If it doesn't implement IContainer, it can't contain stuff.
+        raise TypeError(
+            _('Container is not a valid Zope container.')
+            )
+
+def checkFactory(container, name, factory):
+    __setitem__ = providedBy(container).get('__setitem__')
+    if __setitem__ is not None:
+        precondition = __setitem__.queryTaggedValue('precondition')
+        if precondition is not None:
+            try:
+                precondition = precondition.factory
+            except AttributeError:
+                pass
+            else:
+                try:
+                    precondition(container, name, factory)
+                except zope.interface.Invalid:
+                    return False
+
+    # check the constraint on __parent__
+    __parent__ = factory.getInterfaces().get('__parent__')
+    if __parent__ is not None:
+        try:
+            validate = __parent__.validate
+        except AttributeError:
+            pass
+        else:
+            try:
+                validate(container)
+            except zope.interface.Invalid:
+                return False
+
+    return True
+
+class IItemTypePrecondition(zope.interface.Interface):
+
+    def __call__(container, name, object):
+        """Test whether container setitem arguments are valid.
+
+        Raise zope.interface.Invalid if the object is invalid.
+        """
+
+    def factory(container, name, factory):
+        """Test whether objects provided by the factory are acceptable
+
+        Return a boolean value.
+        """
+
+
+class _TypesBased(object):
+
+    @readproperty
+    def types(self):
+        raw_types, module = self.raw_types
+        types = []
+        for t in raw_types:
+            if isinstance(t, str):
+                t = resolve(t, module)
+            types.append(t)
+
+        self.types = types
+        return types
+
+    def __init__(self, *types, **kw):
+        if [t for t in types if isinstance(t, str)]:
+            # have dotted names
+            module = kw.get('module', sys._getframe(1).f_globals['__name__'])
+            self.raw_types = types, module
+        else:
+            self.types = types
+
+
+class ItemTypePrecondition(_TypesBased):
+    """Specify a `__setitem__` precondition that restricts item types
+
+    Items must be one of the given types.
+
+    >>> class I1(zope.interface.Interface):
+    ...     pass
+    >>> class I2(zope.interface.Interface):
+    ...     pass
+
+
+    >>> precondition = ItemTypePrecondition(I1, I2)
+
+    >>> class Ob(object):
+    ...     pass
+    >>> ob = Ob()
+
+    >>> class Factory(object):
+    ...     def __call__(self):
+    ...         return Ob()
+    ...     def getInterfaces(self):
+    ...         return zope.interface.implementedBy(Ob)
+
+    >>> factory = Factory()
+
+    >>> try:
+    ...     precondition(None, 'foo', ob)
+    ... except InvalidItemType, v:
+    ...     print v[0], (v[1] is ob), (v[2] == (I1, I2))
+    ... else:
+    ...     print 'Should have failed'
+    None True True
+
+    >>> try:
+    ...     precondition.factory(None, 'foo', factory)
+    ... except InvalidItemType, v:
+    ...     print v[0], (v[1] is factory), (v[2] == (I1, I2))
+    ... else:
+    ...     print 'Should have failed'
+    None True True
+
+    >>> zope.interface.classImplements(Ob, I2)
+    >>> precondition(None, 'foo', ob)
+    >>> precondition.factory(None, 'foo', factory)
+
+    """
+
+    zope.interface.implements(IItemTypePrecondition)
+
+    def __call__(self, container, name, object):
+        for iface in self.types:
+            if iface.providedBy(object):
+                return
+        raise InvalidItemType(container, object, self.types)
+
+    def factory(self, container, name, factory):
+        implemented = factory.getInterfaces()
+
+        for iface in self.types:
+            if implemented.isOrExtends(iface):
+               return
+        raise InvalidItemType(container, factory, self.types)
+
+
+def contains(*types):
+    """Declare that a container type contains only the given types
+
+    This is used within a class suite defining an interface to create
+    a __setitem__ specification with a precondition allowing only the
+    given types:
+
+      >>> class IFoo(zope.interface.Interface):
+      ...     pass
+      >>> class IBar(zope.interface.Interface):
+      ...     pass
+      >>> class IFooBarContainer(IContainer):
+      ...     contains(IFoo, IBar)
+
+      >>> __setitem__ = IFooBarContainer['__setitem__']
+      >>> __setitem__.getTaggedValue('precondition').types == (IFoo, IBar)
+      True
+
+    It is invalid to call contains outside a class suite:
+
+      >>> contains(IFoo, IBar)
+      Traceback (most recent call last):
+      ...
+      TypeError: contains not called from suite
+    """
+
+    frame = sys._getframe(1)
+    f_locals = frame.f_locals
+    f_globals = frame.f_globals
+
+    if not (f_locals is not f_globals
+            and f_locals.get('__module__')
+            and f_locals.get('__module__') == f_globals.get('__name__')
+            ):
+        raise TypeError("contains not called from suite")
+
+    def __setitem__(key, value):
+        pass
+    __setitem__.__doc__ = IContainer['__setitem__'].__doc__
+    __setitem__.precondition = ItemTypePrecondition(
+        *types,
+        **dict(module=f_globals['__name__'])
+        )
+    f_locals['__setitem__'] = __setitem__
+
+
+class IContainerTypesConstraint(zope.interface.Interface):
+
+    def __call__(object):
+        """Test whether object is valid.
+
+        Return True if valid.
+        Raise zope.interface.Invalid if the objet is invalid.
+        """
+
+
+class ContainerTypesConstraint(_TypesBased):
+    """Constrain a container to be one of a number of types
+
+    >>> class I1(zope.interface.Interface):
+    ...     pass
+    >>> class I2(zope.interface.Interface):
+    ...     pass
+    >>> class Ob(object):
+    ...     pass
+    >>> ob = Ob()
+    >>> constraint = ContainerTypesConstraint(I1, I2)
+    >>> try:
+    ...     constraint(ob)
+    ... except InvalidContainerType, v:
+    ...     print (v[0] is ob), (v[1] == (I1, I2))
+    ... else:
+    ...     print 'Should have failed'
+    True True
+
+    >>> zope.interface.classImplements(Ob, I2)
+    >>> constraint(Ob())
+    True
+
+    """
+
+    zope.interface.implements(IContainerTypesConstraint)
+
+    def __call__(self, object):
+       for iface in self.types:
+           if iface.providedBy(object):
+               return True
+       else:
+           raise InvalidContainerType(object, self.types)
+
+
+def containers(*types):
+    """Declare the container types a type can be contained in
+
+    This is used within a class suite defining an interface to create
+    a __parent__ specification with a constraint allowing only the
+    given types:
+
+      >>> class IFoo(IContainer):
+      ...     pass
+      >>> class IBar(IContainer):
+      ...     pass
+
+      >>> from zope.container.interfaces import IContained
+      >>> class IFooBarContained(IContained):
+      ...     containers(IFoo, IBar)
+
+      >>> __parent__ = IFooBarContained['__parent__']
+      >>> __parent__.constraint.types == (IFoo, IBar)
+      True
+
+    It is invalid to call containers outside a class suite:
+
+      >>> containers(IFoo, IBar)
+      Traceback (most recent call last):
+      ...
+      TypeError: containers not called from suite
+    """
+
+    frame = sys._getframe(1)
+    f_locals = frame.f_locals
+    f_globals = frame.f_globals
+
+    if not (f_locals is not f_globals
+            and f_locals.get('__module__')
+            and f_locals.get('__module__') == f_globals.get('__name__')
+            ):
+        raise TypeError("containers not called from suite")
+
+    __parent__ = zope.schema.Field(
+        constraint = ContainerTypesConstraint(
+            *types,
+            **dict(module=f_globals['__name__'])
+            )
+        )
+    f_locals['__parent__'] = __parent__
+

Copied: Sandbox/malthe/zope.container/src/zope/container/constraints.txt (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/constraints.txt)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/constraints.txt	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/constraints.txt	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,97 @@
+Containment constraints
+=======================
+
+Containment constraints allow us to express restrictions on the types
+of items that can be placed in containers or on the types of
+containers an item can be placed in.  We express these constraints in
+interfaces.  Let's define some container and item interfaces:
+
+    >>> from zope.container.interfaces import IContainer, IContained
+    >>> from zope.container.constraints import containers, contains
+
+    >>> class IBuddyFolder(IContainer):
+    ...     contains('.IBuddy')
+
+
+In this example, we used the contains function to declare that objects
+that provide IBuddyFolder can only contain items that provide IBuddy.
+Note that we used a string containing a dotted name for the IBuddy
+interface. This is because IBuddy hasn't been defined yet.  When we
+define IBuddy, we can use IBuddyFolder directly:
+
+    >>> class IBuddy(IContained):
+    ...     containers(IBuddyFolder)
+
+
+Now, with these interfaces in place, we can define Buddy and
+BuddyFolder classes and verify that we can put buddies in buddy
+folders:
+
+    >>> from zope import interface
+
+    >>> class Buddy:
+    ...     interface.implements(IBuddy)
+
+    >>> class BuddyFolder:
+    ...     interface.implements(IBuddyFolder)
+
+    >>> from zope.container.constraints import checkObject, checkFactory
+    >>> from zope.component.factory import Factory
+
+    >>> checkObject(BuddyFolder(), 'x', Buddy())
+    >>> checkFactory(BuddyFolder(), 'x', Factory(Buddy))
+    True
+
+If we try to use other containers or folders, we'll get errors:
+
+    >>> class Container:
+    ...     interface.implements(IContainer)
+
+    >>> class Contained:
+    ...     interface.implements(IContained)
+
+    >>> checkObject(Container(), 'x', Buddy())
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    InvalidContainerType: ...
+
+    >>> checkFactory(Container(), 'x', Factory(Buddy))
+    False
+
+    >>> checkObject(BuddyFolder(), 'x', Contained())
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    InvalidItemType: ...
+
+    >>> checkFactory(BuddyFolder(), 'x', Factory(Contained))
+    False
+
+In the example, we defined the container first and then the items.  We
+could have defined these in the opposite order:
+
+    >>> class IContact(IContained):
+    ...     containers('.IContacts')
+
+    >>> class IContacts(IContainer):
+    ...     contains(IContact)
+
+    >>> class Contact:
+    ...     interface.implements(IContact)
+
+    >>> class Contacts:
+    ...     interface.implements(IContacts)
+
+    >>> checkObject(Contacts(), 'x', Contact())
+
+    >>> checkFactory(Contacts(), 'x', Factory(Contact))
+    True
+
+    >>> checkObject(Contacts(), 'x', Buddy())
+    ... # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    InvalidItemType: ...
+
+    >>> checkFactory(Contacts(), 'x', Factory(Buddy))
+    False
+
+

Copied: Sandbox/malthe/zope.container/src/zope/container/find.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/find.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/find.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/find.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,89 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Find Support
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.interface import implements
+from interfaces import IFind, IIdFindFilter, IObjectFindFilter
+from interfaces import IReadContainer
+
+class FindAdapter(object):
+
+    implements(IFind)
+
+    __used_for__ = IReadContainer
+
+    def __init__(self, context):
+        self._context = context
+
+    def find(self, id_filters=None, object_filters=None):
+        'See IFind'
+        id_filters = id_filters or []
+        object_filters = object_filters or []
+        result = []
+        container = self._context
+        for id, object in container.items():
+            _find_helper(id, object, container,
+                         id_filters, object_filters,
+                         result)
+        return result
+
+
+def _find_helper(id, object, container, id_filters, object_filters, result):
+    for id_filter in id_filters:
+        if not id_filter.matches(id):
+            break
+    else:
+        # if we didn't break out of the loop, all name filters matched
+        # now check all object filters
+        for object_filter in object_filters:
+            if not object_filter.matches(object):
+                break
+        else:
+            # if we didn't break out of the loop, all filters matched
+            result.append(object)
+
+    if not IReadContainer.providedBy(object):
+        return
+
+    container = object
+    for id, object in container.items():
+        _find_helper(id, object, container, id_filters, object_filters, result)
+
+class SimpleIdFindFilter(object):
+
+    implements(IIdFindFilter)
+
+    def __init__(self, ids):
+        self._ids = ids
+
+    def matches(self, id):
+        'See INameFindFilter'
+        return id in self._ids
+    
+class SimpleInterfacesFindFilter(object):
+    """Filter objects on the provided interfaces"""
+    implements(IObjectFindFilter)
+    
+    def __init__(self, *interfaces):
+        self.interfaces = interfaces
+    
+    def matches(self, object):
+        for iface in self.interfaces:
+            if iface.providedBy(object):
+                return True
+        return False

Copied: Sandbox/malthe/zope.container/src/zope/container/i18n.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/i18n.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/i18n.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/i18n.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Customization of zope.i18n for the Zope application server
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+# import this as _ to create i18n messages in the zope domain
+from zope.i18nmessageid import MessageFactory
+ZopeMessageFactory = MessageFactory('zope')

Copied: Sandbox/malthe/zope.container/src/zope/container/interfaces.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/interfaces.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/interfaces.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/interfaces.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,341 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Container-related interfaces
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.deprecation import deprecated
+
+from zope.interface import Interface, Attribute, Invalid
+from zope.component.interfaces import IView, IObjectEvent
+from zope.interface.common.mapping import IItemMapping
+from zope.interface.common.mapping import IReadMapping, IEnumerableMapping
+from zope.location.interfaces import ILocation
+from zope.lifecycleevent.interfaces import IObjectModifiedEvent
+
+deprecated('IContentContainer',
+           'This interface has been deprecated. '
+           'Check the "containerViews" zcml directive. '
+           'The reference will be gone in 3.3')
+
+class DuplicateIDError(KeyError):
+    pass
+
+class ContainerError(Exception):
+    """An error of a container with one of its components."""
+
+class InvalidContainerType(Invalid, TypeError):
+    """The type of a container is not valid."""
+
+class InvalidItemType(Invalid, TypeError):
+    """The type of an item is not valid."""
+
+class InvalidType(Invalid, TypeError):
+    """The type of an object is not valid."""
+
+
+
+class IContained(ILocation):
+    """Objects contained in containers."""
+
+
+class IItemContainer(IItemMapping):
+    """Minimal readable container."""
+
+
+class ISimpleReadContainer(IItemContainer, IReadMapping):
+    """Readable content containers."""
+
+
+class IReadContainer(ISimpleReadContainer, IEnumerableMapping):
+    """Readable containers that can be enumerated."""
+
+
+class IWriteContainer(Interface):
+    """An interface for the write aspects of a container."""
+
+    def __setitem__(name, object):
+        """Add the given `object` to the container under the given name.
+
+        Raises a ``TypeError`` if the key is not a unicode or ascii string.
+        Raises a ``ValueError`` if key is empty.
+
+        The container might choose to add a different object than the
+        one passed to this method.
+
+        If the object doesn't implement `IContained`, then one of two
+        things must be done:
+
+        1. If the object implements `ILocation`, then the `IContained`
+           interface must be declared for the object.
+
+        2. Otherwise, a `ContainedProxy` is created for the object and
+           stored.
+
+        The object's `__parent__` and `__name__` attributes are set to the
+        container and the given name.
+
+        If the old parent was ``None``, then an `IObjectAddedEvent` is
+        generated, otherwise, an `IObjectMovedEvent` is generated.  An
+        `IContainerModifiedEvent` is generated for the container.
+
+        If the object replaces another object, then the old object is
+        deleted before the new object is added, unless the container
+        vetos the replacement by raising an exception.
+
+        If the object's `__parent__` and `__name__` were already set to
+        the container and the name, then no events are generated and
+        no hooks.  This allows advanced clients to take over event
+        generation.
+
+        """
+
+    def __delitem__(name):
+        """Delete the named object from the container.
+
+        Raises a ``KeyError`` if the object is not found.
+
+        If the deleted object's `__parent__` and `__name__` match the
+        container and given name, then an `IObjectRemovedEvent` is
+        generated and the attributes are set to ``None``. If the object
+        can be adapted to `IObjectMovedEvent`, then the adapter's
+        `moveNotify` method is called with the event.
+
+        Unless the object's `__parent__` and `__name__` attributes were
+        initially ``None``, generate an `IContainerModifiedEvent` for the
+        container.
+
+        If the object's `__parent__` and `__name__` were already set to
+        ``None``, then no events are generated.  This allows advanced
+        clients to take over event generation.
+
+        """
+
+
+class IItemWriteContainer(IWriteContainer, IItemContainer):
+    """A write container that also supports minimal reads."""
+
+
+class IContentContainer(IWriteContainer):
+    """Containers (like folders) that contain ordinary content."""
+
+
+class IContainer(IReadContainer, IWriteContainer):
+    """Readable and writable content container."""
+
+
+class IBTreeContainer(IContainer):
+    """Container that supports BTree semantics for some methods."""
+
+    def items(key=None):
+        """Return an iterator over the key-value pairs in the container.
+
+        If ``None`` is passed as `key`, this method behaves as if no argument
+        were passed; exactly as required for ``IContainer.items()``.
+
+        If `key` is in the container, the first item provided by the iterator
+        will correspond to that key.  Otherwise, the first item will be for
+        the key that would come next if `key` were in the container.
+
+        """
+
+    def keys(key=None):
+        """Return an iterator over the keys in the container.
+
+        If ``None`` is passed as `key`, this method behaves as if no argument
+        were passed; exactly as required for ``IContainer.keys()``.
+
+        If `key` is in the container, the first key provided by the iterator
+        will be that key.  Otherwise, the first key will be the one that would
+        come next if `key` were in the container.
+
+        """
+
+    def values(key=None):
+        """Return an iterator over the values in the container.
+
+        If ``None`` is passed as `key`, this method behaves as if no argument
+        were passed; exactly as required for ``IContainer.values()``.
+
+        If `key` is in the container, the first value provided by the iterator
+        will correspond to that key.  Otherwise, the first value will be for
+        the key that would come next if `key` were in the container.
+
+        """
+
+
+class IOrderedContainer(IContainer):
+    """Containers whose contents are maintained in order."""
+
+    def updateOrder(order):
+        """Revise the order of keys, replacing the current ordering.
+
+        order is a list or a tuple containing the set of existing keys in
+        the new order. `order` must contain ``len(keys())`` items and cannot
+        contain duplicate keys.
+
+        Raises ``TypeError`` if order is not a tuple or a list.
+
+        Raises ``ValueError`` if order contains an invalid set of keys.
+        """
+
+
+class IContainerNamesContainer(IContainer):
+    """Containers that always choose names for their items."""
+
+
+##############################################################################
+# Moving Objects
+
+class IObjectMovedEvent(IObjectEvent):
+    """An object has been moved."""
+
+    oldParent = Attribute("The old location parent for the object.")
+    oldName = Attribute("The old location name for the object.")
+    newParent = Attribute("The new location parent for the object.")
+    newName = Attribute("The new location name for the object.")
+
+
+##############################################################################
+# Adding objects
+
+class UnaddableError(ContainerError):
+    """An object cannot be added to a container."""
+
+    def __init__(self, container, obj, message=""):
+        self.container = container
+        self.obj = obj
+        self.message = message and ": %s" % message
+
+    def __str__(self):
+        return ("%(obj)s cannot be added "
+                "to %(container)s%(message)s" % self.__dict__)
+
+
+class IObjectAddedEvent(IObjectMovedEvent):
+    """An object has been added to a container."""
+
+
+class IAdding(IView):
+
+    def add(content):
+        """Add content object to container.
+
+        Add using the name in `contentName`.  Returns the added object
+        in the context of its container.
+
+        If `contentName` is already used in container, raises
+        ``DuplicateIDError``.
+        """
+
+    contentName = Attribute(
+         """The content name, as usually set by the Adder traverser.
+
+         If the content name hasn't been defined yet, returns ``None``.
+
+         Some creation views might use this to optionally display the
+         name on forms.
+         """
+         )
+
+    def nextURL():
+        """Return the URL that the creation view should redirect to.
+
+        This is called by the creation view after calling add.
+
+        It is the adder's responsibility, not the creation view's to
+        decide what page to display after content is added.
+        """
+
+    def nameAllowed():
+        """Return whether names can be input by the user."""
+
+    def addingInfo():
+        """Return add menu data as a sequence of mappings.
+
+        Each mapping contains 'action', 'title', and possibly other keys.
+
+        The result is sorted by title.
+        """
+
+    def isSingleMenuItem():
+        """Return whether there is single menu item or not."""
+
+    def hasCustomAddView():
+        "This should be called only if there is `singleMenuItem` else return 0"
+
+
+class INameChooser(Interface):
+
+    def checkName(name, object):
+        """Check whether an object name is valid.
+
+        Raises a user error if the name is not valid.
+        """
+
+    def chooseName(name, object):
+        """Choose a unique valid name for the object
+
+        The given name and object may be taken into account when
+        choosing the name.
+        """
+
+
+##############################################################################
+# Removing objects
+
+
+class IObjectRemovedEvent(IObjectMovedEvent):
+    """An object has been removed from a container."""
+
+
+##############################################################################
+# Modifying containers
+
+
+class IContainerModifiedEvent(IObjectModifiedEvent):
+    """The container has been modified.
+
+    This event is specific to "containerness" modifications, which means
+    addition, removal or reordering of sub-objects.
+    """
+
+
+##############################################################################
+# Finding objects
+
+class IFind(Interface):
+    """
+    Find support for containers.
+    """
+
+    def find(id_filters=None, object_filters=None):
+        """Find object that matches all filters in all sub-objects.
+
+        This container itself is not included.
+        """
+
+
+class IObjectFindFilter(Interface):
+
+    def matches(object):
+        """Return True if the object matches the filter criteria."""
+
+
+class IIdFindFilter(Interface):
+
+    def matches(id):
+        """Return True if the id matches the filter criteria."""

Copied: Sandbox/malthe/zope.container/src/zope/container/property.py (from rev 85591, zope.cachedescriptors/trunk/src/zope/cachedescriptors/property.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/property.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/property.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,106 @@
+##############################################################################
+# Copyright (c) 2008 Zope Corporation 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.
+##############################################################################
+"""Cached properties
+
+See the CachedProperty class.
+
+$Id$
+"""
+
+ncaches = 0l
+
+
+class CachedProperty(object):
+    """Cached Properties.
+    """
+
+    def __init__(self, func, *names):
+        global ncaches
+        ncaches += 1
+        self.data = (func, names,
+                     "_v_cached_property_key_%s" % ncaches,
+                     "_v_cached_property_value_%s" % ncaches)
+
+    def __get__(self, inst, class_):
+        if inst is None:
+            return self
+
+        func, names, key_name, value_name = self.data
+
+        key = names and [getattr(inst, name) for name in names]
+        value = getattr(inst, value_name, self)
+
+        if value is not self:
+            # We have a cached value
+            if key == getattr(inst, key_name, self):
+                # Cache is still good!
+                return value
+
+        # We need to compute and cache the value
+
+        value = func(inst)
+        setattr(inst, key_name, key)
+        setattr(inst, value_name, value)
+
+        return value
+
+
+class Lazy(object):
+    """Lazy Attributes.
+    """
+
+    def __init__(self, func, name=None):
+        if name is None:
+            name = func.__name__
+        self.data = (func, name)
+
+    def __get__(self, inst, class_):
+        if inst is None:
+            return self
+
+        func, name = self.data
+        value = func(inst)
+        inst.__dict__[name] = value
+
+        return value
+
+
+class readproperty(object):
+
+    def __init__(self, func):
+        self.func = func
+
+    def __get__(self, inst, class_):
+        if inst is None:
+            return self
+
+        func = self.func
+        return func(inst)
+
+
+class cachedIn(object):
+    """Cached property with given cache attribute."""
+
+    def __init__(self, attribute_name):
+        self.attribute_name = attribute_name
+
+    def __call__(self, func):
+
+        def get(instance):
+            try:
+                value = getattr(instance, self.attribute_name)
+            except AttributeError:
+                value = func(instance)
+                setattr(instance, self.attribute_name, value)
+            return value
+
+        return property(get)

Copied: Sandbox/malthe/zope.container/src/zope/container/property.txt (from rev 85591, zope.cachedescriptors/trunk/src/zope/cachedescriptors/property.txt)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/property.txt	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/property.txt	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,208 @@
+Cached Properties
+=================
+
+Cached properties are computed properties that cache their computed
+values.  They take into account instance attributes that they depend
+on, so when the instance attributes change, the properties will change
+the values they return.
+
+Cached properties cache their data in _v_ attributes, so they are
+also useful for managing the computation of volatile attributes for
+persistent objects. Let's look at an example::
+
+    >>> from zope.container import property
+    >>> import math
+
+    >>> class Point:
+    ... 
+    ...     def __init__(self, x, y):
+    ...         self.x, self.y = x, y
+    ...
+    ...     def radius(self):
+    ...         print 'computing radius'
+    ...         return math.sqrt(self.x**2 + self.y**2)
+    ...     radius = property.CachedProperty(radius, 'x', 'y')
+
+    >>> point = Point(1.0, 2.0)   
+
+If we ask for the radius the first time::
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+We see that the radius function is called, but if we ask for it again::
+
+    >>> '%.2f' % point.radius
+    '2.24'
+
+The function isn't called.  If we change one of the attribute the
+radius depends on, it will be recomputed::
+
+    >>> point.x = 2.0
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.83'
+
+But changing other attributes doesn't cause recomputation::
+
+    >>> point.q = 1
+    >>> '%.2f' % point.radius
+    '2.83'
+
+Note that we don't have any non-volitile attributes added::
+
+    >>> names = [name for name in point.__dict__ if not name.startswith('_v_')]
+    >>> names.sort()
+    >>> names
+    ['q', 'x', 'y']
+
+
+Lazy Computed Attributes
+------------------------
+
+The `property` module provides another descriptor that supports a
+slightly different caching model: lazy attributes.  Like cached
+proprties, they are computed the first time they are used. however,
+they aren't stored in volatile attributes and they aren't
+automatically updated when other attributes change.  Furthermore, the
+store their data using their attribute name, thus overriding
+themselves. This provides much faster attribute access after the
+attribute has been computed. Let's look at the previous example using
+lazy attributes::
+
+    >>> class Point:
+    ... 
+    ...     def __init__(self, x, y):
+    ...         self.x, self.y = x, y
+    ...
+    ...     def radius(self):
+    ...         print 'computing radius'
+    ...         return math.sqrt(self.x**2 + self.y**2)
+    ...     radius = property.Lazy(radius)
+
+    >>> point = Point(1.0, 2.0)   
+
+If we ask for the radius the first time::
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+We see that the radius function is called, but if we ask for it again::
+
+    >>> '%.2f' % point.radius
+    '2.24'
+
+The function isn't called.  If we change one of the attribute the
+radius depends on, it still isn't called::
+    
+    >>> point.x = 2.0
+    >>> '%.2f' % point.radius
+    '2.24'
+
+If we want the radius to be recomputed, we have to manually delete it::
+
+    >>> del point.radius
+
+    >>> point.x = 2.0
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.83'
+
+Note that the radius is stored in the instance dictionary::
+
+    >>> '%.2f' % point.__dict__['radius']
+    '2.83'
+
+The lazy attribute needs to know the attribute name.  It normally
+deduces the attribute name from the name of the function passed. If we
+want to use a different name, we need to pass it::
+
+    >>> def d(point):
+    ...     print 'computing diameter'
+    ...     return 2*point.radius
+
+    >>> Point.diameter = property.Lazy(d, 'diameter')
+    >>> '%.2f' % point.diameter
+    computing diameter
+    '5.66'
+
+
+readproperties
+==============
+
+readproperties are like lazy computed attributes except that the
+attribute isn't set by the property::
+
+
+    >>> class Point:
+    ... 
+    ...     def __init__(self, x, y):
+    ...         self.x, self.y = x, y
+    ...
+    ...     def radius(self):
+    ...         print 'computing radius'
+    ...         return math.sqrt(self.x**2 + self.y**2)
+    ...     radius = property.readproperty(radius)
+
+    >>> point = Point(1.0, 2.0)   
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+But you *can* replace the property by setting a value. This is the major
+difference to the builtin `property`::
+
+    >>> point.radius = 5
+    >>> point.radius
+    5
+
+
+cachedIn
+========
+
+The `cachedIn` property allows to specify the attribute where to store the
+computed value::
+
+    >>> class Point:
+    ... 
+    ...     def __init__(self, x, y):
+    ...         self.x, self.y = x, y
+    ...
+    ...     @property.cachedIn('_radius_attribute')
+    ...     def radius(self):
+    ...         print 'computing radius'
+    ...         return math.sqrt(self.x**2 + self.y**2)
+    
+    >>> point = Point(1.0, 2.0)   
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+    >>> '%.2f' % point.radius
+    '2.24'
+
+The radius is cached in the attribute with the given name, `_radius_attribute`
+in this case::
+
+    >>> '%.2f' % point._radius_attribute
+    '2.24'
+
+When the attribute is removed the radius is re-calculated once. This allows
+invalidation::
+
+    >>> del point._radius_attribute
+
+    >>> '%.2f' % point.radius
+    computing radius
+    '2.24'
+
+    >>> '%.2f' % point.radius
+    '2.24'

Copied: Sandbox/malthe/zope.container/src/zope/container/size.py (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/size.py)
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/size.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/size.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Adapters that give the size of an object.
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+from zope.container.i18n import ZopeMessageFactory as _
+from zope.size.interfaces import ISized
+from zope.interface import implements
+
+class ContainerSized(object):
+
+    implements(ISized)
+
+    def __init__(self, container):
+        self._container = container
+
+    def sizeForSorting(self):
+        """See `ISized`"""
+        return ('item', len(self._container))
+
+    def sizeForDisplay(self):
+        """See `ISized`"""
+        num_items = len(self._container)
+        if num_items == 1:
+            return _('1 item')
+        return _('${items} items', mapping={'items': str(num_items)})

Copied: Sandbox/malthe/zope.container/src/zope/container/tests (from rev 85590, Sandbox/malthe/zope.container/src/zope/app/container/tests)

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/placelesssetup.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/placelesssetup.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/placelesssetup.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,25 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Unit test logic for setting up and tearing down basic infrastructure
-
-$Id$
-"""
-from zope.app.testing import ztapi
-from zope.app.container.interfaces import IWriteContainer, INameChooser
-from zope.app.container.contained import NameChooser
-
-class PlacelessSetup(object):
-
-    def setUp(self):
-        ztapi.provideAdapter(IWriteContainer, INameChooser, NameChooser)

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_btree.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_btree.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_btree.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,165 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""BTree Container Tests
-
-$Id$
-"""
-from unittest import TestCase, main, makeSuite, TestSuite
-from zope.interface.verify import verifyObject
-from zope.testing.doctestunit import DocTestSuite
-from zope.app.testing import placelesssetup
-from test_icontainer import TestSampleContainer
-from zope.app.container.btree import BTreeContainer
-from zope.app.container.interfaces import IBTreeContainer
-
-
-class TestBTreeContainer(TestSampleContainer, TestCase):
-
-    def makeTestObject(self):
-        return BTreeContainer()
-
-
-class TestBTreeSpecials(TestCase):
-
-    def testStoredLength(self):
-        # This is lazy for backward compatibility.  If the len is not
-        # stored already we set it to the length of the underlying
-        # btree.
-        bc = BTreeContainer()
-        self.assertEqual(bc.__dict__['_BTreeContainer__len'](), 0)
-        del bc.__dict__['_BTreeContainer__len']
-        self.failIf(bc.__dict__.has_key('_BTreeContainer__len'))
-        bc['1'] = 1
-        self.assertEqual(len(bc), 1)
-        self.assertEqual(bc.__dict__['_BTreeContainer__len'](), 1)
-
-    # The tests which follow test the additional signatures and declarations
-    # for the BTreeContainer that allow it to provide the IBTreeContainer
-    # interface.
-
-    def testBTreeContainerInterface(self):
-        bc = BTreeContainer()
-        self.assert_(verifyObject(IBTreeContainer, bc))
-        self.checkIterable(bc.items())
-        self.checkIterable(bc.keys())
-        self.checkIterable(bc.values())
-
-    def testEmptyItemsWithArg(self):
-        bc = BTreeContainer()
-        self.assertEqual(list(bc.items(None)), list(bc.items()))
-        self.assertEqual(list(bc.items("")), [])
-        self.assertEqual(list(bc.items("not-there")), [])
-        self.checkIterable(bc.items(None))
-        self.checkIterable(bc.items(""))
-        self.checkIterable(bc.items("not-there"))
-
-    def testEmptyKeysWithArg(self):
-        bc = BTreeContainer()
-        self.assertEqual(list(bc.keys(None)), list(bc.keys()))
-        self.assertEqual(list(bc.keys("")), [])
-        self.assertEqual(list(bc.keys("not-there")), [])
-        self.checkIterable(bc.keys(None))
-        self.checkIterable(bc.keys(""))
-        self.checkIterable(bc.keys("not-there"))
-
-    def testEmptyValuesWithArg(self):
-        bc = BTreeContainer()
-        self.assertEqual(list(bc.values(None)), list(bc.values()))
-        self.assertEqual(list(bc.values("")), [])
-        self.assertEqual(list(bc.values("not-there")), [])
-        self.checkIterable(bc.values(None))
-        self.checkIterable(bc.values(""))
-        self.checkIterable(bc.values("not-there"))
-
-    def testNonemptyItemsWithArg(self):
-        bc = BTreeContainer()
-        bc["0"] = 1
-        bc["1"] = 2
-        bc["2"] = 3
-        self.assertEqual(list(bc.items(None)), list(bc.items()))
-        self.assertEqual(list(bc.items("")), [("0", 1), ("1", 2), ("2", 3)])
-        self.assertEqual(list(bc.items("3")), [])
-        self.assertEqual(list(bc.items("2.")), [])
-        self.assertEqual(list(bc.items("2")), [("2", 3)])
-        self.assertEqual(list(bc.items("1.")), [("2", 3)])
-        self.assertEqual(list(bc.items("1")), [("1", 2), ("2", 3)])
-        self.assertEqual(list(bc.items("0.")), [("1", 2), ("2", 3)])
-        self.assertEqual(list(bc.items("0")), [("0", 1), ("1", 2), ("2", 3)])
-        self.checkIterable(bc.items(None))
-        self.checkIterable(bc.items(""))
-        self.checkIterable(bc.items("0."))
-        self.checkIterable(bc.items("3"))
-
-    def testNonemptyKeysWithArg(self):
-        bc = BTreeContainer()
-        bc["0"] = 1
-        bc["1"] = 2
-        bc["2"] = 3
-        self.assertEqual(list(bc.keys(None)), list(bc.keys()))
-        self.assertEqual(list(bc.keys("")), ["0", "1", "2"])
-        self.assertEqual(list(bc.keys("3")), [])
-        self.assertEqual(list(bc.keys("2.")), [])
-        self.assertEqual(list(bc.keys("2")), ["2"])
-        self.assertEqual(list(bc.keys("1.")), ["2"])
-        self.assertEqual(list(bc.keys("1")), ["1", "2"])
-        self.assertEqual(list(bc.keys("0.")), ["1", "2"])
-        self.assertEqual(list(bc.keys("0")), ["0", "1", "2"])
-        self.checkIterable(bc.keys(None))
-        self.checkIterable(bc.keys(""))
-        self.checkIterable(bc.keys("0."))
-        self.checkIterable(bc.keys("3"))
-
-    def testNonemptyValueWithArg(self):
-        bc = BTreeContainer()
-        bc["0"] = 1
-        bc["1"] = 2
-        bc["2"] = 3
-        self.assertEqual(list(bc.values(None)), list(bc.values()))
-        self.assertEqual(list(bc.values("")), [1, 2, 3])
-        self.assertEqual(list(bc.values("3")), [])
-        self.assertEqual(list(bc.values("2.")), [])
-        self.assertEqual(list(bc.values("2")), [3])
-        self.assertEqual(list(bc.values("1.")), [3])
-        self.assertEqual(list(bc.values("1")), [2, 3])
-        self.assertEqual(list(bc.values("0.")), [2, 3])
-        self.assertEqual(list(bc.values("0")), [1, 2, 3])
-        self.checkIterable(bc.values(None))
-        self.checkIterable(bc.values(""))
-        self.checkIterable(bc.values("0."))
-        self.checkIterable(bc.values("3"))
-
-    def checkIterable(self, iterable):
-        it = iter(iterable)
-        self.assert_(callable(it.next))
-        self.assert_(callable(it.__iter__))
-        self.assert_(iter(it) is it)
-        # Exhaust the iterator:
-        first_time = list(it)
-        self.assertRaises(StopIteration, it.next)
-        # Subsequent iterations will return the same values:
-        self.assertEqual(list(iterable), first_time)
-        self.assertEqual(list(iterable), first_time)
-
-
-def test_suite():
-    return TestSuite((
-        makeSuite(TestBTreeContainer),
-        makeSuite(TestBTreeSpecials),
-        DocTestSuite('zope.app.container.btree',
-                     setUp=placelesssetup.setUp,
-                     tearDown=placelesssetup.tearDown),
-        ))
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Modified: Sandbox/malthe/zope.container/src/zope/container/tests/test_constraints.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_constraints.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_constraints.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2003 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -19,14 +19,14 @@
 from zope.testing import doctest, module
 
 def setUp(test):
-    module.setUp(test, 'zope.app.container.constraints_txt')
+    module.setUp(test, 'zope.container.constraints_txt')
 
 def tearDown(test):
-    module.tearDown(test, 'zope.app.container.constraints_txt')
+    module.tearDown(test, 'zope.container.constraints_txt')
 
 def test_suite():
     return unittest.TestSuite((
-        doctest.DocTestSuite('zope.app.container.constraints'),
+        doctest.DocTestSuite('zope.container.constraints'),
         doctest.DocFileSuite('../constraints.txt',
                              setUp=setUp, tearDown=tearDown),
         ))

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_contained.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_contained.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_contained.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,327 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Contained Tests
-
-$Id$
-"""
-import unittest
-import gc
-from ZODB.DemoStorage import DemoStorage
-from ZODB.DB import DB
-import transaction
-from persistent import Persistent
-
-import zope.interface
-from zope.testing import doctest
-
-from zope.app.container.contained import ContainedProxy
-from zope.app.testing import placelesssetup
-
-class MyOb(Persistent):
-    pass
-
-def test_basic_proxy_attribute_management_and_picklability():
-    """Contained-object proxy
-
-    This is a picklable proxy that can be put around objects that
-    don't implement IContained.
-
-    >>> l = [1, 2, 3]
-    >>> p = ContainedProxy(l)
-    >>> p.__parent__ = 'Dad'
-    >>> p.__name__ = 'p'
-    >>> p
-    [1, 2, 3]
-    >>> p.__parent__
-    'Dad'
-    >>> p.__name__
-    'p'
-
-    >>> import pickle
-    >>> p2 = pickle.loads(pickle.dumps(p))
-    >>> p2
-    [1, 2, 3]
-    >>> p2.__parent__
-    'Dad'
-    >>> p2.__name__
-    'p'
-    """
-
-def test_basic_persistent_w_non_persistent_proxied():
-    """
-    >>> p = ContainedProxy([1])
-    >>> p.__parent__ = 2
-    >>> p.__name__ = 'test'
-    >>> db = DB(DemoStorage('test_storage'))
-    >>> c = db.open()
-    >>> c.root()['p'] = p
-    >>> transaction.commit()
-
-    >>> c2 = db.open()
-    >>> p2 = c2.root()['p']
-    >>> p2
-    [1]
-    >>> p2.__parent__
-    2
-    >>> p2.__name__
-    'test'
-
-    >>> p2._p_changed
-    0
-    >>> p2._p_deactivate()
-    >>> p2._p_changed
-    >>> p2.__name__
-    'test'
-
-    >>> db.close()
-    """
-
-def test_declarations_on_ContainedProxy():
-    r"""
-
-    It is possible to make declarations on ContainedProxy objects.
-
-      >>> class I1(zope.interface.Interface):
-      ...     pass
-      >>> class C(object):
-      ...     zope.interface.implements(I1)
-
-      >>> c = C()
-      >>> p = ContainedProxy(c)
-
-    ContainedProxy provides no interfaces on it's own:
-
-      >>> tuple(zope.interface.providedBy(ContainedProxy))
-      ()
-
-    It implements IContained and IPersistent:
-
-      >>> tuple(zope.interface.implementedBy(ContainedProxy))
-      (<InterfaceClass zope.app.container.interfaces.IContained>,
-       <InterfaceClass persistent.interfaces.IPersistent>)
-
-    A proxied object has IContainer, in addition to what the unproxied
-    object has:
-
-      >>> tuple(zope.interface.providedBy(p))
-      (<InterfaceClass zope.app.container.tests.test_contained.I1>,
-       <InterfaceClass zope.app.container.interfaces.IContained>,
-       <InterfaceClass persistent.interfaces.IPersistent>)
-
-      >>> class I2(zope.interface.Interface):
-      ...     pass
-      >>> zope.interface.directlyProvides(c, I2)
-      >>> tuple(zope.interface.providedBy(p))
-      (<InterfaceClass zope.app.container.tests.test_contained.I2>,
-       <InterfaceClass zope.app.container.tests.test_contained.I1>,
-       <InterfaceClass zope.app.container.interfaces.IContained>,
-       <InterfaceClass persistent.interfaces.IPersistent>)
-
-    We can declare interfaces through the proxy:
-
-      >>> class I3(zope.interface.Interface):
-      ...     pass
-      >>> zope.interface.directlyProvides(p, I3)
-      >>> tuple(zope.interface.providedBy(p))
-      (<InterfaceClass zope.app.container.tests.test_contained.I3>,
-       <InterfaceClass zope.app.container.tests.test_contained.I1>,
-       <InterfaceClass zope.app.container.interfaces.IContained>,
-       <InterfaceClass persistent.interfaces.IPersistent>)
-
-    """
-
-def test_basic_persistent_w_persistent_proxied():
-    """
-
-    Here, we'll verify that shared references work and
-    that updates to both the proxies and the proxied objects
-    are made correctly.
-
-            ----------------------
-            |                    |
-          parent                other
-            |                 /
-           ob  <--------------
-
-    Here we have an object, parent, that contains ob.  There is another
-    object, other, that has a non-container reference to ob.
-
-    >>> parent = MyOb()
-    >>> parent.ob = ContainedProxy(MyOb())
-    >>> parent.ob.__parent__ = parent
-    >>> parent.ob.__name__ = 'test'
-    >>> other = MyOb()
-    >>> other.ob = parent.ob
-
-    We can change ob through either parent or other
-
-    >>> parent.ob.x = 1
-    >>> other.ob.y = 2
-
-    Now we'll save the data:
-
-    >>> db = DB(DemoStorage('test_storage'))
-    >>> c1 = db.open()
-    >>> c1.root()['parent'] = parent
-    >>> c1.root()['other'] = other
-    >>> transaction.commit()
-
-    We'll open a second connection and verify that we have the data we
-    expect:
-
-    >>> c2 = db.open()
-    >>> p2 = c2.root()['parent']
-    >>> p2.ob.__parent__ is p2
-    1
-    >>> p2.ob.x
-    1
-    >>> p2.ob.y
-    2
-    >>> o2 = c2.root()['other']
-    >>> o2.ob is p2.ob
-    1
-    >>> o2.ob is p2.ob
-    1
-    >>> o2.ob.__name__
-    'test'
-
-    Now we'll change things around a bit. We'll move things around
-    a bit. We'll also add an attribute to ob
-
-    >>> o2.ob.__name__ = 'test 2'
-    >>> o2.ob.__parent__ = o2
-    >>> o2.ob.z = 3
-
-    >>> p2.ob.__parent__ is p2
-    0
-    >>> p2.ob.__parent__ is o2
-    1
-
-    And save the changes:
-
-    >>> transaction.commit()
-
-    Now we'll reopen the first connection and verify that we can see
-    the changes:
-
-    >>> c1.close()
-    >>> c1 = db.open()
-    >>> p2 = c1.root()['parent']
-    >>> p2.ob.__name__
-    'test 2'
-    >>> p2.ob.z
-    3
-    >>> p2.ob.__parent__ is c1.root()['other']
-    1
-
-    >>> db.close()
-    """
-
-def test_proxy_cache_interaction():
-    """Test to make sure the proxy properly interacts with the object cache
-
-    Persistent objects are their own weak refs.  Thier deallocators
-    need to notify their connection's cache that their object is being
-    deallocated, so that it is removed from the cache.
-
-    >>> from ZODB.tests.util import DB
-    >>> db = DB()
-    >>> db.setCacheSize(5)
-    >>> conn = db.open()
-    >>> conn.root()['p'] = ContainedProxy(None)
-
-    We need to create some filler objects to push our proxy out of the cache:
-
-    >>> for i in range(10):
-    ...     conn.root()[i] = MyOb()
-
-    >>> transaction.commit()
-
-    Let's get the oid of our proxy:
-
-    >>> oid = conn.root()['p']._p_oid
-
-    Now, we'll access the filler object's:
-
-    >>> x = [getattr(conn.root()[i], 'x', 0) for i in range(10)]
-
-    We've also accessed the root object. If we garbage-collect the
-    cache:
-
-    >>> conn._cache.incrgc()
-
-    Then the root object will still be active, because it was accessed
-    recently:
-
-    >>> conn.root()._p_changed
-    0
-
-    And the proxy will be in the cache, because it's refernced from
-    the root object:
-
-    >>> conn._cache.get(oid) is not None
-    True
-
-    But it's a ghost:
-
-    >>> conn.root()['p']._p_changed
-
-    If we deactivate the root object:
-
-    >>> conn.root()._p_deactivate()
-
-    Then we'll release the last reference to the proxy and it should
-    no longer be in the cache. To be sure, we'll call gc:
-
-    >>> x = gc.collect()
-    >>> conn._cache.get(oid) is not None
-    False
-
-    """
-
-def test_ContainedProxy_instances_have_no_instance_dictionaries():
-    """Make sure that proxies don't introduce extra instance dictionaries
-
-    >>> from zope.app.container.contained import ContainedProxy
-    >>> class C:
-    ...     pass
-
-    >>> c = C()
-    >>> c.x = 1
-    >>> c.__dict__
-    {'x': 1}
-
-    >>> p = ContainedProxy(c)
-    >>> p.__dict__
-    {'x': 1}
-    >>> p.y = 3
-    >>> p.__dict__
-    {'y': 3, 'x': 1}
-    >>> c.__dict__
-    {'y': 3, 'x': 1}
-
-    >>> p.__dict__ is c.__dict__
-    True
-    
-    """
-
-def test_suite():
-    return unittest.TestSuite((
-        doctest.DocTestSuite('zope.app.container.contained',
-                             setUp=placelesssetup.setUp,
-                             tearDown=placelesssetup.tearDown),
-        doctest.DocTestSuite(optionflags=doctest.NORMALIZE_WHITESPACE),
-        ))
-
-if __name__ == '__main__': unittest.main()

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraversable.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_containertraversable.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraversable.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,70 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Container Traverser tests.
-
-$Id$
-"""
-import unittest
-from zope.testing.cleanup import CleanUp
-from zope.interface import implements
-from zope.traversing.interfaces import TraversalError
-
-from zope.app.container.traversal import ContainerTraversable
-from zope.app.container.interfaces import IContainer
-
-class Container(object):
-
-    implements(IContainer)
-
-    def __init__(self, attrs={}, objs={}):
-        for attr,value in attrs.iteritems():
-            setattr(self, attr, value)
-
-        self.__objs = {}
-        for name,value in objs.iteritems():
-            self.__objs[name] = value
-
-
-    def __getitem__(self, name):
-        return self.__objs[name]
-
-    def get(self, name, default=None):
-        return self.__objs.get(name, default)
-
-    def __contains__(self, name):
-        return self.__objs.has_key(name)
-
-
-class Test(CleanUp, unittest.TestCase):
-    def testAttr(self):
-        # test container path traversal
-        foo = Container()
-        bar = Container()
-        baz = Container()
-        c   = Container({'foo': foo}, {'bar': bar, 'foo': baz})
-
-        T = ContainerTraversable(c)
-        self.failUnless(T.traverse('foo', []) is baz)
-        self.failUnless(T.traverse('bar', []) is bar)
-
-        self.assertRaises(TraversalError , T.traverse, 'morebar', [])
-
-
-def test_suite():
-    loader = unittest.TestLoader()
-    return loader.loadTestsFromTestCase(Test)
-
-
-if __name__ == '__main__':
-    unittest.TextTestRunner().run(test_suite())

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraverser.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_containertraverser.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_containertraverser.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,94 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Container Traverser Tests
-
-$Id$
-"""
-import unittest
-from zope.app.container.traversal import ContainerTraverser
-from zope.app.container.interfaces import IReadContainer
-from zope.app.testing import ztapi, placelesssetup
-from zope.publisher.interfaces import NotFound
-from zope.publisher.browser import TestRequest
-from zope.interface import implements
-
-class TestContainer(object):
-    implements(IReadContainer)
-
-    def __init__(self, **kw):
-        for name, value in kw.items():
-            setattr(self, name , value)
-
-    def get(self, name, default=None):
-        return getattr(self, name, default)
-
-
-class View(object):
-    def __init__(self, context, request):
-        self.context = context
-        self.request = request
-
-
-class TraverserTest(placelesssetup.PlacelessSetup, unittest.TestCase):
-
-    # The following two methods exist, so that other container traversers can
-    # use these tests as a base.
-    def _getTraverser(self, context, request):
-        return ContainerTraverser(context, request)
-
-    def _getContainer(self, **kw):
-        return TestContainer(**kw)
-
-    def setUp(self):
-        super(TraverserTest, self).setUp()
-        # Create a small object tree
-        self.foo = self._getContainer()
-        foo2 = self._getContainer(Foo=self.foo)
-        # Initiate a request
-        self.request = TestRequest()
-        # Create the traverser
-        self.traverser = self._getTraverser(foo2, self.request)
-        # Define a simple view for the container
-        ztapi.browserView(IReadContainer, 'viewfoo', View)
-        
-    def test_itemTraversal(self):
-        self.assertEqual(
-            self.traverser.publishTraverse(self.request, 'Foo'),
-            self.foo)
-        self.assertRaises(
-            NotFound,
-            self.traverser.publishTraverse, self.request, 'morebar')
-
-    def test_viewTraversal(self):
-        self.assertEquals(
-            self.traverser.publishTraverse(self.request, 'viewfoo').__class__,
-            View)
-        self.assertEquals(
-            self.traverser.publishTraverse(self.request, 'Foo'),
-            self.foo)
-        self.assertRaises(
-            NotFound,
-            self.traverser.publishTraverse, self.request, 'morebar')
-        self.assertRaises(
-            NotFound,
-            self.traverser.publishTraverse, self.request, '@@morebar')
-
-
-def test_suite():
-    return unittest.TestSuite((
-        unittest.makeSuite(TraverserTest),
-        ))
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_dependency.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_dependency.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_dependency.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,52 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 Zope Corporation 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.
-#
-##############################################################################
-"""Test the CheckDependency event subscriber.
-
-$Id$
-"""
-import unittest
-
-from zope.interface import implements
-from zope.app.dependable.interfaces import IDependable, DependencyError
-from zope.app.container.contained import ObjectRemovedEvent
-from zope.app.container.dependency import CheckDependency
-from zope.traversing.interfaces import IPhysicallyLocatable
-
-class DummyObject(object):
-
-    implements(IDependable, IPhysicallyLocatable)
-
-    def dependents(self):
-        return ['dependency1', 'dependency2']
-
-    def getPath(self):
-        return '/dummy-object'
-
-
-class Test(unittest.TestCase):
-
-    def testCheckDependency(self):
-        obj = DummyObject()
-        parent = object()
-        event = ObjectRemovedEvent(obj, parent, 'oldName')
-        self.assertRaises(DependencyError, CheckDependency, event)
-
-
-def test_suite():
-    return unittest.TestSuite((
-            unittest.makeSuite(Test),
-            ))
-
-if __name__=='__main__':
-    unittest.main()

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_directory.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_directory.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_directory.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,39 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""FS-based directory implementation tests for containers
-
-$Id$
-"""
-from unittest import TestCase, TestSuite, main, makeSuite
-import zope.app.container.directory
-
-class Directory(object):
-    pass
- 
-class Test(TestCase):
-
-    def test_Cloner(self):
-        d = Directory()
-        d.a = 1
-        clone = zope.app.container.directory.Cloner(d)('foo')
-        self.assert_(clone != d)
-        self.assertEqual(clone.__class__, d.__class__)
-
-def test_suite():
-    return TestSuite((
-        makeSuite(Test),
-        ))
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Modified: Sandbox/malthe/zope.container/src/zope/container/tests/test_find.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_find.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_find.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -16,10 +16,10 @@
 $Id$
 """
 from unittest import TestCase, main, makeSuite
-from zope.app.container.interfaces import IReadContainer
-from zope.app.container.interfaces import IObjectFindFilter
-from zope.app.container.find import FindAdapter, SimpleIdFindFilter
-from zope.app.container.find import SimpleInterfacesFindFilter
+from zope.container.interfaces import IReadContainer
+from zope.container.interfaces import IObjectFindFilter
+from zope.container.find import FindAdapter, SimpleIdFindFilter
+from zope.container.find import SimpleInterfacesFindFilter
 from zope.interface import implements, Interface, directlyProvides
 
 class FakeContainer(object):

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_icontainer.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_icontainer.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_icontainer.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,319 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Test the IContainer interface.
-
-$Id$
-"""
-from unittest import TestCase, main, makeSuite
-
-from zope.interface.verify import verifyObject
-from zope.app.container.interfaces import IContainer
-from zope.app.testing import placelesssetup
-
-
-def DefaultTestData():
-    return [('3', '0'), ('2', '1'), ('4', '2'), ('6', '3'), ('0', '4'),
-            ('5', '5'), ('1', '6'), ('8', '7'), ('7', '8'), ('9', '9')]
-
-class BaseTestIContainer(placelesssetup.PlacelessSetup):
-    """Base test cases for containers.
-
-    Subclasses must define a makeTestObject that takes no
-    arguments and that returns a new empty test container,
-    and a makeTestData that also takes no arguments and returns
-    a sequence of (key, value) pairs that may be stored in
-    the test container.  The list must be at least ten items long.
-    'NoSuchKey' may not be used as a key value in the returned list.
-    """
-
-    def __setUp(self):
-        self.__container = container = self.makeTestObject()
-        self.__data = data = self.makeTestData()
-        for k, v in data:
-            container[k] = v
-        return container, data
-
-    ############################################################
-    # Interface-driven tests:
-
-    def testIContainerVerify(self):
-        verifyObject(IContainer, self.makeTestObject())
-
-    def test_keys(self):
-        # See interface IReadContainer
-        container = self.makeTestObject()
-        keys = container.keys()
-        self.assertEqual(list(keys), [])
-
-        container, data = self.__setUp()
-        keys = container.keys()
-        keys = list(keys); keys.sort() # convert to sorted list
-        ikeys = [ k for k, v in data ]; ikeys.sort() # sort input keys
-        self.assertEqual(keys, ikeys)
-
-    def test_get(self):
-        # See interface IReadContainer
-        default = object()
-        data = self.makeTestData()
-        container = self.makeTestObject()
-        self.assertRaises(KeyError, container.__getitem__, data[0][0])
-        self.assertEqual(container.get(data[0][0], default), default)
-
-        container, data = self.__setUp()
-        self.assertRaises(KeyError, container.__getitem__,
-                          self.getUnknownKey())
-        self.assertEqual(container.get(self.getUnknownKey(), default), default)
-        for i in (1, 8, 7, 3, 4):
-            self.assertEqual(container.get(data[i][0], default), data[i][1])
-            self.assertEqual(container.get(data[i][0]), data[i][1])
-
-    def test_values(self):
-        # See interface IReadContainer
-        container = self.makeTestObject()
-        values = container.values()
-        self.assertEqual(list(values), [])
-
-        container, data = self.__setUp()
-        values = list(container.values())
-        for k, v in data:
-            try:
-                values.remove(v)
-            except ValueError:
-                self.fail('Value not in list')
-                
-        self.assertEqual(values, [])
-
-    def test_len(self):
-        # See interface IReadContainer
-        container = self.makeTestObject()
-        self.assertEqual(len(container), 0)
-
-        container, data = self.__setUp()
-        self.assertEqual(len(container), len(data))
-
-    def test_items(self):
-        # See interface IReadContainer
-        container = self.makeTestObject()
-        items = container.items()
-        self.assertEqual(list(items), [])
-
-        container, data = self.__setUp()
-        items = container.items()
-        items = list(items); items.sort() # convert to sorted list
-        data.sort()                       # sort input data
-        self.assertEqual(items, data)
-
-    def test___contains__(self):
-        # See interface IReadContainer
-        container = self.makeTestObject()
-        data = self.makeTestData()
-        self.assertEqual(not not (data[6][0] in container), False)
-
-        container, data = self.__setUp()
-        self.assertEqual(not not (data[6][0] in container), True)
-        for i in (1, 8, 7, 3, 4):
-            self.assertEqual(not not (data[i][0] in container), 1)
-
-    def test_delObject(self):
-        # See interface IWriteContainer
-        default = object()
-        data = self.makeTestData()
-        container = self.makeTestObject()
-        self.assertRaises(KeyError, container.__delitem__, data[0][0])
-
-        container, data = self.__setUp()
-        self.assertRaises(KeyError, container.__delitem__,
-                          self.getUnknownKey())
-        for i in (1, 8, 7, 3, 4):
-            del container[data[i][0]]
-        for i in (1, 8, 7, 3, 4):
-            self.assertRaises(KeyError, container.__getitem__, data[i][0])
-            self.assertEqual(container.get(data[i][0], default), default)
-        for i in (0, 2, 9, 6, 5):
-            self.assertEqual(container[data[i][0]], data[i][1])
-
-    ############################################################
-    # Tests from Folder
-
-    def testEmpty(self):
-        folder = self.makeTestObject()
-        data = self.makeTestData()
-        self.failIf(folder.keys())
-        self.failIf(folder.values())
-        self.failIf(folder.items())
-        self.failIf(len(folder))
-        self.failIf(data[6][0] in folder)
-
-        self.assertEquals(folder.get(data[6][0], None), None)
-        self.assertRaises(KeyError, folder.__getitem__, data[6][0])
-
-        self.assertRaises(KeyError, folder.__delitem__, data[6][0])
-
-    def testBadKeyTypes(self):
-        folder = self.makeTestObject()
-        data = self.makeTestData()
-        value = data[1][1]
-        for name in self.getBadKeyTypes():
-            self.assertRaises(TypeError, folder.__setitem__, name, value)
-
-    def testOneItem(self):
-        folder = self.makeTestObject()
-        data = self.makeTestData()
-
-        foo = data[0][1]
-        name = data[0][0]
-        folder[name] = foo
-
-        self.assertEquals(len(folder.keys()), 1)
-        self.assertEquals(folder.keys()[0], name)
-        self.assertEquals(len(folder.values()), 1)
-        self.assertEquals(folder.values()[0], foo)
-        self.assertEquals(len(folder.items()), 1)
-        self.assertEquals(folder.items()[0], (name, foo))
-        self.assertEquals(len(folder), 1)
-
-        self.failUnless(name in folder)
-        # Use an arbitrary id frpm the data set; don;t just use any id, since
-        # there might be restrictions on their form
-        self.failIf(data[6][0] in folder)
-
-        self.assertEquals(folder.get(name, None), foo)
-        self.assertEquals(folder[name], foo)
-
-        self.assertRaises(KeyError, folder.__getitem__, data[6][0])
-
-        foo2 = data[1][1]
-        
-        name2 = data[1][0]
-        folder[name2] = foo2
-
-        self.assertEquals(len(folder.keys()), 2)
-        self.assertEquals(not not name2 in folder.keys(), True)
-        self.assertEquals(len(folder.values()), 2)
-        self.assertEquals(not not foo2 in folder.values(), True)
-        self.assertEquals(len(folder.items()), 2)
-        self.assertEquals(not not (name2, foo2) in folder.items(), True)
-        self.assertEquals(len(folder), 2)
-
-        del folder[name]
-        del folder[name2]
-
-        self.failIf(folder.keys())
-        self.failIf(folder.values())
-        self.failIf(folder.items())
-        self.failIf(len(folder))
-        self.failIf(name in folder)
-
-        self.assertRaises(KeyError, folder.__getitem__, name)
-        self.assertEquals(folder.get(name, None), None)
-        self.assertRaises(KeyError, folder.__delitem__, name)
-
-    def testManyItems(self):
-        folder = self.makeTestObject()
-        data = self.makeTestData()
-        objects = [ data[i][1] for i in range(4) ]
-        name0 = data[0][0]
-        name1 = data[1][0]
-        name2 = data[2][0]
-        name3 = data[3][0]
-        folder[name0] = objects[0]
-        folder[name1] = objects[1]
-        folder[name2] = objects[2]
-        folder[name3] = objects[3]
-
-        self.assertEquals(len(folder.keys()), len(objects))
-        self.failUnless(name0 in folder.keys())
-        self.failUnless(name1 in folder.keys())
-        self.failUnless(name2 in folder.keys())
-        self.failUnless(name3 in folder.keys())
-
-        self.assertEquals(len(folder.values()), len(objects))
-        self.failUnless(objects[0] in folder.values())
-        self.failUnless(objects[1] in folder.values())
-        self.failUnless(objects[2] in folder.values())
-        self.failUnless(objects[3] in folder.values())
-
-        self.assertEquals(len(folder.items()), len(objects))
-        self.failUnless((name0, objects[0]) in folder.items())
-        self.failUnless((name1, objects[1]) in folder.items())
-        self.failUnless((name2, objects[2]) in folder.items())
-        self.failUnless((name3, objects[3]) in folder.items())
-
-        self.assertEquals(len(folder), len(objects))
-
-        self.failUnless(name0 in folder)
-        self.failUnless(name1 in folder)
-        self.failUnless(name2 in folder)
-        self.failUnless(name3 in folder)
-        self.failIf(data[5][0] in folder)
-
-        self.assertEquals(folder.get(name0, None), objects[0])
-        self.assertEquals(folder[name0], objects[0])
-        self.assertEquals(folder.get(name1, None), objects[1])
-        self.assertEquals(folder[name1], objects[1])
-        self.assertEquals(folder.get(name2, None), objects[2])
-        self.assertEquals(folder[name2], objects[2])
-        self.assertEquals(folder.get(name3, None), objects[3])
-        self.assertEquals(folder[name3], objects[3])
-
-        self.assertEquals(folder.get(data[5][0], None), None)
-        self.assertRaises(KeyError, folder.__getitem__, data[5][0])
-
-        del folder[name0]
-        self.assertEquals(len(folder), len(objects) - 1)
-        self.failIf(name0 in folder)
-        self.failIf(name0 in folder.keys())
-
-        self.failIf(objects[0] in folder.values())
-        self.failIf((name0, objects[0]) in folder.items())
-
-        self.assertEquals(folder.get(name0, None), None)
-        self.assertRaises(KeyError, folder.__getitem__, name0)
-
-        self.assertRaises(KeyError, folder.__delitem__, name0)
-
-        del folder[name1]
-        del folder[name2]
-        del folder[name3]
-
-        self.failIf(folder.keys())
-        self.failIf(folder.values())
-        self.failIf(folder.items())
-        self.failIf(len(folder))
-        self.failIf(name0 in folder)
-        self.failIf(name1 in folder)
-        self.failIf(name2 in folder)
-        self.failIf(name3 in folder)
-
-
-class TestSampleContainer(BaseTestIContainer, TestCase):
-
-    def makeTestObject(self):
-        from zope.app.container.sample import SampleContainer
-        return SampleContainer()
-
-    def makeTestData(self):
-        return DefaultTestData()
-
-    def getUnknownKey(self):
-        return '10'
-
-    def getBadKeyTypes(self):
-        return [None, ['foo'], 1, '\xf3abc']
-
-def test_suite():
-    return makeSuite(TestSampleContainer)
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_objectcopier.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_objectcopier.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_objectcopier.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,211 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Object Copier Tests
-
-$Id$
-"""
-from unittest import TestCase, TestSuite, main, makeSuite
-
-import zope.component
-from zope.testing import doctest
-from zope.traversing.api import traverse
-from zope.component.eventtesting import getEvents, clearEvents
-from zope.copypastemove import ObjectCopier
-from zope.copypastemove.interfaces import IObjectCopier
-
-from zope.app.component.testing import PlacefulSetup
-from zope.app.testing import setup
-from zope.app.folder import Folder
-
-class File(object):
-    pass
-
-def test_copy_events():
-    """
-    Prepare the setup::
-
-      >>> root = setup.placefulSetUp(site=True)
-      >>> zope.component.provideAdapter(ObjectCopier, (None,), IObjectCopier)
-
-    Prepare some objects::
-
-      >>> folder = Folder()
-      >>> root[u'foo'] = File()
-      >>> root[u'folder'] = folder
-      >>> list(folder.keys())
-      []
-      >>> foo = traverse(root, 'foo') # wrap in ContainedProxy
-
-    Now make a copy::
-
-      >>> clearEvents()
-      >>> copier = IObjectCopier(foo)
-      >>> copier.copyTo(folder, u'bar')
-      u'bar'
-
-    Check that the copy has been done::
-
-      >>> list(folder.keys())
-      [u'bar']
-
-    Check what events have been sent::
-
-      >>> events = getEvents()
-      >>> [event.__class__.__name__ for event in events]
-      ['ObjectCopiedEvent', 'ObjectAddedEvent', 'ContainerModifiedEvent']
-
-    Check that the ObjectCopiedEvent includes the correct data::
-
-      >>> events[0].object is folder[u'bar']
-      True
-      >>> events[0].original is root[u'foo']
-      True
-
-    Finally, tear down::
-
-      >>> setup.placefulTearDown()
-    """
-
-
-class ObjectCopierTest(PlacefulSetup, TestCase):
-
-    def setUp(self):
-        PlacefulSetup.setUp(self)
-        PlacefulSetup.buildFolders(self)
-        zope.component.provideAdapter(ObjectCopier, (None,), IObjectCopier)
-
-    def test_copytosame(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        copier.copyTo(container, 'file1')
-        self.failUnless('file1' in container)
-        self.failUnless('file1-2' in container)
-
-    def test_copytosamewithnewname(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        copier.copyTo(container, 'file2')
-        self.failUnless('file1' in container)
-        self.failUnless('file2' in container)
-
-    def test_copytoother(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        copier.copyTo(target, 'file1')
-        self.failUnless('file1' in container)
-        self.failUnless('file1' in target)
-
-    def test_copytootherwithnewname(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        copier.copyTo(target, 'file2')
-        self.failUnless('file1' in container)
-        self.failUnless('file2' in target)
-
-    def test_copytootherwithnamecollision(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        target['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        copier.copyTo(target, 'file1')
-        # we do it twice, just to test auto-name generation
-        copier.copyTo(target, 'file1')
-        self.failUnless('file1' in container)
-        self.failUnless('file1' in target)
-        self.failUnless('file1-2' in target)
-        self.failUnless('file1-3' in target)
-
-    def test_copyable(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        self.failUnless(copier.copyable())
-
-    def test_copyableTo(self):
-        #  A file should be copyable to a folder that has an
-        #  object with the same id.
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        copier = IObjectCopier(file)
-        self.failUnless(copier.copyableTo(container, 'file1'))
-        
-    def test_copyfoldertosibling(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2')
-        source = traverse(root, '/folder1/folder1_1')
-        copier = IObjectCopier(source)
-        copier.copyTo(target)
-        self.failUnless('folder1_1' in target)
-
-    def test_copyfoldertosame(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder1')
-        source = traverse(root, '/folder1/folder1_1')
-        copier = IObjectCopier(source)
-        copier.copyTo(target)
-        self.failUnless('folder1_1' in target)
-
-    def test_copyfoldertosame2(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder1/folder1_1')
-        source = traverse(root, '/folder1/folder1_1/folder1_1_1')
-        copier = IObjectCopier(source)
-        copier.copyTo(target)
-        self.failUnless('folder1_1_1' in target)
-
-    def test_copyfolderfromroot(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2')
-        source = traverse(root, '/folder1')
-        copier = IObjectCopier(source)
-        copier.copyTo(target)
-        self.failUnless('folder1' in target)
-
-    def test_copyfolderfromroot2(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2/folder2_1/folder2_1_1')
-        source = traverse(root, '/folder1')
-        copier = IObjectCopier(source)
-        copier.copyTo(target)
-        self.failUnless('folder1' in target)
-
-def test_suite():
-    return TestSuite((
-        makeSuite(ObjectCopierTest),
-        doctest.DocTestSuite(),
-        ))
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_objectmover.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_objectmover.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_objectmover.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,227 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation 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.
-#
-##############################################################################
-"""Object Mover Tests
-
-$Id$
-"""
-from unittest import TestCase, TestSuite, main, makeSuite
-
-import zope.component
-from zope.testing import doctest
-from zope.traversing.api import traverse
-from zope.component.eventtesting import getEvents, clearEvents
-from zope.copypastemove import ObjectMover
-from zope.copypastemove.interfaces import IObjectMover
-
-from zope.app.component.testing import PlacefulSetup
-from zope.app.testing import setup
-from zope.app.folder import Folder
-
-class File(object):
-    pass
-
-def test_move_events():
-    """
-    Prepare the setup::
-
-      >>> root = setup.placefulSetUp(site=True)
-      >>> zope.component.provideAdapter(ObjectMover, (None,), IObjectMover)
-
-    Prepare some objects::
-
-      >>> folder = Folder()
-      >>> root[u'foo'] = File()
-      >>> root[u'folder'] = folder
-      >>> list(folder.keys())
-      []
-      >>> foo = traverse(root, 'foo') # wrap in ContainedProxy
-
-    Now move it::
-
-      >>> clearEvents()
-      >>> mover = IObjectMover(foo)
-      >>> mover.moveableTo(folder)
-      True
-      >>> mover.moveTo(folder, u'bar')
-      u'bar'
-
-    Check that the move has been done::
-
-      >>> list(root.keys())
-      [u'folder']
-      >>> list(folder.keys())
-      [u'bar']
-
-    Check what events have been sent::
-
-      >>> events = getEvents()
-      >>> [event.__class__.__name__ for event in events]
-      ['ObjectMovedEvent', 'ContainerModifiedEvent', 'ContainerModifiedEvent']
-
-    Verify that the ObjectMovedEvent includes the correct data::
-
-      >>> events[0].oldName, events[0].newName
-      (u'foo', u'bar')
-      >>> events[0].oldParent is root
-      True
-      >>> events[0].newParent is folder
-      True
-
-    Let's look the other events:
-
-      >>> events[1].object is folder
-      True
-      >>> events[2].object is root
-      True
-
-    Finally, tear down::
-
-      >>> setup.placefulTearDown()
-    """
-
-
-class ObjectMoverTest(PlacefulSetup, TestCase):
-
-    def setUp(self):
-        PlacefulSetup.setUp(self)
-        PlacefulSetup.buildFolders(self)
-        zope.component.provideAdapter(ObjectMover, (None,), )
- 
-    def test_movetosame(self):
-        # Should be a noop, because "moving" to same location
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        mover.moveTo(container, 'file1')
-        self.failUnless('file1' in container)
-        self.assertEquals(len(container), 3)
-
-    def test_movetosamewithnewname(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        mover.moveTo(container, 'file2')
-        self.failIf('file1' in container)
-        self.failUnless('file2' in container)
-
-    def test_movetoother(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        mover.moveTo(target, 'file1')
-        self.failIf('file1' in container)
-        self.failUnless('file1' in target)
-
-    def test_movetootherwithnewname(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        mover.moveTo(target, 'file2')
-        self.failIf('file1' in container)
-        self.failUnless('file2' in target)
-
-    def test_movetootherwithnamecollision(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        target = traverse(root, 'folder2')
-        target['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        mover.moveTo(target, 'file1')
-        self.failIf('file1' in container)
-        self.failUnless('file1' in target)
-        self.failUnless('file1-2' in target)
-
-    def test_moveable(self):
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        self.failUnless(mover.moveable())
-
-    def test_moveableTo(self):
-        #  A file should be moveable to a folder that has an
-        #  object with the same id.
-        root = self.rootFolder
-        container = traverse(root, 'folder1')
-        container['file1'] = File()
-        file = traverse(root, 'folder1/file1')
-        mover = IObjectMover(file)
-        self.failUnless(mover.moveableTo(container, 'file1'))
-
-    def test_movefoldertosibling(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2')
-        source = traverse(root, '/folder1/folder1_1')
-        mover = IObjectMover(source)
-        mover.moveTo(target)
-        self.failUnless('folder1_1' in target)
-
-    def test_movefoldertosame(self):
-        # Should be a noop, because "moving" to same location
-        root = self.rootFolder
-        target = traverse(root, '/folder1')
-        source = traverse(root, '/folder1/folder1_1')
-        mover = IObjectMover(source)
-        mover.moveTo(target)
-        self.failUnless('folder1_1' in target)
-        self.assertEquals(len(target), 2)
-
-    def test_movefoldertosame2(self):
-        # Should be a noop, because "moving" to same location
-        root = self.rootFolder
-        target = traverse(root, '/folder1/folder1_1')
-        source = traverse(root, '/folder1/folder1_1/folder1_1_1')
-        mover = IObjectMover(source)
-        mover.moveTo(target)
-        self.failUnless('folder1_1_1' in target)
-        self.assertEquals(len(target), 2)
-
-    def test_movefolderfromroot(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2')
-        source = traverse(root, '/folder1')
-        mover = IObjectMover(source)
-        mover.moveTo(target)
-        self.failUnless('folder1' in target)
-
-    def test_movefolderfromroot2(self):
-        root = self.rootFolder
-        target = traverse(root, '/folder2/folder2_1/folder2_1_1')
-        source = traverse(root, '/folder1')
-        mover = IObjectMover(source)
-        mover.moveTo(target)
-        self.failUnless('folder1' in target)
-
-        
-def test_suite():
-    return TestSuite((
-        makeSuite(ObjectMoverTest),
-        doctest.DocTestSuite(),
-        ))
-
-if __name__=='__main__':
-    main(defaultTest='test_suite')

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_ordered.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_ordered.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_ordered.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,101 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2003 Zope Corporation 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.
-#
-##############################################################################
-"""Test the OrderedContainer.
-
-$Id$
-"""
-import unittest
-from zope.testing.doctestunit import DocTestSuite
-from zope.component.eventtesting import getEvents, clearEvents
-from zope.app.testing import placelesssetup, setup
-
-def test_order_events():
-    """
-    Prepare the setup::
-
-        >>> root = setup.placefulSetUp(site=True)
-
-    Prepare some objects::
-
-        >>> from zope.app.container.ordered import OrderedContainer
-        >>> oc = OrderedContainer()
-        >>> oc['foo'] = 'bar'
-        >>> oc['baz'] = 'quux'
-        >>> oc['zork'] = 'grue'
-        >>> oc.keys()
-        ['foo', 'baz', 'zork']
-
-    Now change the order::
-
-        >>> clearEvents()
-        >>> oc.updateOrder(['baz', 'foo', 'zork'])
-        >>> oc.keys()
-        ['baz', 'foo', 'zork']
-
-    Check what events have been sent::
-
-        >>> events = getEvents()
-        >>> [event.__class__.__name__ for event in events]
-        ['ContainerModifiedEvent']
-
-    This is in fact a specialized modification event::
-
-        >>> from zope.lifecycleevent.interfaces import IObjectModifiedEvent
-        >>> IObjectModifiedEvent.providedBy(events[0])
-        True
-
-    Finally, tear down::
-
-        >>> setup.placefulTearDown()
-    """
-
-def test_all_items_available_at_object_added_event():
-    """
-    Prepare the setup::
-
-        >>> root = setup.placefulSetUp(site=True)
-
-    Now register an event subscriber to object added events.
-
-        >>> import zope.component
-        >>> from zope.app.container import interfaces
-
-        >>> @zope.component.adapter(interfaces.IObjectAddedEvent)
-        ... def printContainerKeys(event):
-        ...     print event.newParent.keys()
-
-        >>> zope.component.provideHandler(printContainerKeys)
-
-    Now we are adding an object to the container. 
-
-        >>> from zope.app.container.ordered import OrderedContainer
-        >>> oc = OrderedContainer()
-        >>> oc['foo'] = 'FOO'
-        ['foo']
-
-    Finally, tear down::
-
-        >>> setup.placefulTearDown()
-    """
-
-def test_suite():
-    suite = unittest.TestSuite()
-    suite.addTest(DocTestSuite("zope.app.container.ordered",
-                               setUp=placelesssetup.setUp,
-                               tearDown=placelesssetup.tearDown))
-    suite.addTest(DocTestSuite())
-    return suite
-
-if __name__ == '__main__':
-    unittest.main()

Added: Sandbox/malthe/zope.container/src/zope/container/tests/test_property.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/container/tests/test_property.py	                        (rev 0)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_property.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2008 Zope Corporation 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.
+#
+##############################################################################
+"""Container constraint tests
+
+$Id: test_constraints.py 40495 2005-12-02 17:51:22Z efge $
+"""
+import unittest
+from zope.testing import doctest, module
+
+def setUp(test):
+    module.setUp(test, 'zope.container.property_txt')
+
+def tearDown(test):
+    module.tearDown(test, 'zope.container.property_txt')
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('../property.txt',
+                             setUp=setUp, tearDown=tearDown),
+        ))
+
+if __name__ == '__main__': unittest.main()

Modified: Sandbox/malthe/zope.container/src/zope/container/tests/test_size.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_size.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_size.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,6 +1,6 @@
 ##############################################################################
 #
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# Copyright (c) 2008 Zope Corporation and Contributors.
 # All Rights Reserved.
 #
 # This software is subject to the provisions of the Zope Public License,
@@ -19,7 +19,7 @@
 
 from zope.interface import implements
 from zope.size.interfaces import ISized
-from zope.app.container.interfaces import IContainer
+from zope.container.interfaces import IContainer
 
 class DummyContainer(object):
 
@@ -35,12 +35,12 @@
 class Test(unittest.TestCase):
 
     def testImplementsISized(self):
-        from zope.app.container.size import ContainerSized
+        from zope.container.size import ContainerSized
         sized = ContainerSized(DummyContainer(23))
         self.assert_(ISized.providedBy(sized))
 
     def testEmptyContainer(self):
-        from zope.app.container.size import ContainerSized
+        from zope.container.size import ContainerSized
         obj = DummyContainer(0)
         sized = ContainerSized(obj)
         self.assertEqual(sized.sizeForSorting(), ('item', 0))
@@ -48,14 +48,14 @@
         self.assertEqual(sized.sizeForDisplay().mapping['items'], '0')
 
     def testOneItem(self):
-        from zope.app.container.size import ContainerSized
+        from zope.container.size import ContainerSized
         obj = DummyContainer(1)
         sized = ContainerSized(obj)
         self.assertEqual(sized.sizeForSorting(), ('item', 1))
         self.assertEqual(sized.sizeForDisplay(), u'1 item')
 
     def testSeveralItems(self):
-        from zope.app.container.size import ContainerSized
+        from zope.container.size import ContainerSized
         obj = DummyContainer(2)
         sized = ContainerSized(obj)
         self.assertEqual(sized.sizeForSorting(), ('item', 2))

Deleted: Sandbox/malthe/zope.container/src/zope/container/tests/test_view_permissions.py
===================================================================
--- Sandbox/malthe/zope.container/src/zope/app/container/tests/test_view_permissions.py	2008-04-22 12:11:58 UTC (rev 85590)
+++ Sandbox/malthe/zope.container/src/zope/container/tests/test_view_permissions.py	2008-04-22 12:37:09 UTC (rev 85592)
@@ -1,103 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2004 Zope Corporation 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.
-#
-##############################################################################
-"""Container View Permissions Tests
-
-$Id$
-"""
-import unittest
-import transaction
-
-from zope.security.interfaces import Unauthorized
-
-from zope.app.testing.functional import BrowserTestCase
-from zope.app.file import File
-from zope.dublincore.interfaces import IZopeDublinCore
-from zope.securitypolicy.interfaces import IRolePermissionManager
-from zope.app.container.testing import AppContainerLayer
-
-class Tests(BrowserTestCase):
-
-    def test_default_view_permissions(self):
-        """Tests the default view permissions.
-
-        See zope/app/securitypolicy/configure.zcml for the grants of
-        zope.View and zope.app.dublincore.view to zope.Anonymous. These
-        ensure that, by default, anonymous users can view container contents.
-        """
-        # add an item that can be viewed from the root folder
-        file = File()
-        self.getRootFolder()['file'] = file
-        IZopeDublinCore(file).title = u'My File'
-        transaction.commit()
-
-        response = self.publish('/')
-        self.assertEquals(response.getStatus(), 200)
-        body = response.getBody()
-
-        # confirm we can see the file name
-        self.assert_(body.find('<a href="file">file</a>') != -1)
-
-        # confirm we can see the metadata title
-        self.assert_(body.find('<td><span>My File</span></td>') != -1)
-
-    def test_deny_view(self):
-        """Tests the denial of view permissions to anonymous.
-
-        This test uses the ZMI interface to deny anonymous zope.View permission
-        to the root folder.
-        """
-        # deny zope.View to zope.Anonymous
-        prm = IRolePermissionManager(self.getRootFolder())
-        prm.denyPermissionToRole('zope.View', 'zope.Anonymous')
-        transaction.commit()
-
-        # confirm Unauthorized when viewing root folder
-        self.assertRaises(Unauthorized, self.publish, '/')
-
-    def test_deny_dublincore_view(self):
-        """Tests the denial of dublincore view permissions to anonymous.
-
-        Users who can view a folder contents page but cannot view dublin core
-        should still be able to see the folder items' names, but not their
-        title, modified, and created info.
-        """
-        # add an item that can be viewed from the root folder
-        file = File()
-        self.getRootFolder()['file'] = file
-        IZopeDublinCore(file).title = u'My File'
-
-        # deny zope.app.dublincore.view to zope.Anonymous
-        prm = IRolePermissionManager(self.getRootFolder())
-        prm.denyPermissionToRole('zope.app.dublincore.view', 'zope.Anonymous')
-        transaction.commit()
-
-        response = self.publish('/')
-        self.assertEquals(response.getStatus(), 200)
-        body = response.getBody()
-
-        # confirm we can see the file name
-        self.assert_(body.find('<a href="file">file</a>') != -1)
-
-        # confirm we *cannot* see the metadata title
-        self.assert_(body.find('My File') == -1)
-
-
-def test_suite():
-    suite = unittest.TestSuite()
-    Tests.layer = AppContainerLayer
-    suite.addTest(unittest.makeSuite(Tests))
-    return suite
-
-if __name__=='__main__':
-    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list