[Zope3-checkins] CVS: Zope3/src/zope/app/container - __init__.py:1.2 btree.py:1.2 configure.zcml:1.2 dependency.py:1.2 find.py:1.2 sample.py:1.2 traversal.py:1.2 zopecontainer.py:1.2
Jim Fulton
jim@zope.com
Wed, 25 Dec 2002 09:13:48 -0500
Update of /cvs-repository/Zope3/src/zope/app/container
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/app/container
Added Files:
__init__.py btree.py configure.zcml dependency.py find.py
sample.py traversal.py zopecontainer.py
Log Message:
Grand renaming:
- Renamed most files (especially python modules) to lower case.
- Moved views and interfaces into separate hierarchies within each
project, where each top-level directory under the zope package
is a separate project.
- Moved everything to src from lib/python.
lib/python will eventually go away. I need access to the cvs
repository to make this happen, however.
There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.
=== Zope3/src/zope/app/container/__init__.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/__init__.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.
=== Zope3/src/zope/app/container/btree.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/btree.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# 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.0 (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.
+#
+##############################################################################
+"""
+This module provides a sample container implementation.
+
+This is primarily for testing purposes.
+
+It might be useful as a mix-in for some classes, but many classes will
+need a very different implementation.
+
+Revision information:
+$Id$
+"""
+
+from persistence import Persistent
+from zodb.btrees.OOBTree import OOBTree
+from zope.app.container.sample import SampleContainer
+
+class BTreeContainer(SampleContainer, Persistent):
+
+ __implements__ = SampleContainer.__implements__, Persistent.__implements__
+
+ def _Container__newData(self):
+ """Construct an item-data container
+
+ Subclasses should override this if they want different data.
+
+ The value returned is a mapping object that also has get,
+ has_key, keys, items, and values methods.
+ """
+ return OOBTree()
=== Zope3/src/zope/app/container/configure.zcml 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/configure.zcml Wed Dec 25 09:12:46 2002
@@ -0,0 +1,47 @@
+<zopeConfigure
+ xmlns='http://namespaces.zope.org/zope'
+ xmlns:browser='http://namespaces.zope.org/browser'
+ xmlns:xmlrpc='http://namespaces.zope.org/xmlrpc'
+ xmlns:event="http://namespaces.zope.org/event"
+>
+
+ <adapter
+ provides="zope.app.interfaces.container.find.IFind"
+ for="zope.app.interfaces.container.IReadContainer"
+ permission="zope.ManageContent"
+ factory="zope.app.container.find.FindAdapter" />
+
+ <browser:view
+ name="_traverse"
+ for="zope.app.interfaces.container.IItemContainer"
+ factory="zope.app.container.traversal.ItemTraverser" />
+
+ <browser:view
+ name="_traverse"
+ for="zope.app.interfaces.container.ISimpleReadContainer"
+ factory="zope.app.container.traversal.ContainerTraverser" />
+
+ <xmlrpc:view
+ name="_traverse"
+ for="zope.app.interfaces.container.IItemContainer"
+ factory="zope.app.container.traversal.ItemTraverser" />
+
+ <xmlrpc:view
+ name="_traverse"
+ for="zope.app.interfaces.container.IReadContainer"
+ factory="zope.app.container.traversal.ContainerTraverser" />
+
+ <adapter factory="zope.app.container.traversal.ContainerTraversable"
+ provides="zope.app.interfaces.traversing.traversable.ITraversable"
+ for="zope.app.interfaces.container.IReadContainer" />
+
+ <adapter factory="zope.app.container.zopecontainer.ZopeContainerAdapter"
+ provides="zope.app.interfaces.container.IZopeContainer"
+ for="zope.app.interfaces.container.IContainer" />
+
+ <event:subscribe
+ subscriber = ".dependency.CheckDependency"
+ event_types = "zope.app.interfaces.event.IObjectRemovedEvent"
+ />
+
+</zopeConfigure>
=== Zope3/src/zope/app/container/dependency.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/dependency.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Objects that take care of annotating dublin core meta data times
+
+$Id$
+"""
+from zope.component import queryAdapter
+from zope.app.interfaces.dependable import IDependable
+from zope.app.interfaces.dependable import DependencyError
+from zope.interfaces.event import ISubscriber
+from zope.proxy.introspection import removeAllProxies
+from zope.app.traversing import getPhysicalPathString, locationAsUnicode
+
+class DependencyChecker:
+ """Checking dependency while deleting object
+ """
+ __implements__ = ISubscriber
+
+ def __init__(self):
+ pass
+
+ def notify(self, event):
+ object = removeAllProxies(event.object)
+ dependency = queryAdapter(object, IDependable)
+ if dependency is not None:
+ dependents = dependency.dependents()
+ if dependents:
+ objectpath = getPhysicalPathString(event.object)
+ dependents = map(locationAsUnicode, dependents)
+ raise DependencyError("Removal of object (%s)"
+ " which has dependents (%s)"
+ % (objectpath,
+ ", ".join(dependents)))
+
+CheckDependency = DependencyChecker()
=== Zope3/src/zope/app/container/find.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/find.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,81 @@
+##############################################################################
+#
+# 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.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+
+"""
+
+from zope.app.interfaces.container.find import IFind, IIdFindFilter
+from zope.app.interfaces.container import IReadContainer
+# XXX need to do this manually to wrap objects
+from zope.proxy.context import ContextWrapper
+
+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():
+ object = ContextWrapper(object, container, name=id)
+ _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.isImplementedBy(object):
+ return
+
+ container = object
+ for id, object in container.items():
+ object = ContextWrapper(object, container, name=id)
+ _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
=== Zope3/src/zope/app/container/sample.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/sample.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,101 @@
+##############################################################################
+#
+# 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.0 (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.
+#
+##############################################################################
+"""
+This module provides a sample container implementation.
+
+This is primarily for testing purposes.
+
+It might be useful as a mix-in for some classes, but many classes will
+need a very different implementation.
+
+Revision information:
+$Id$
+"""
+
+from zope.app.interfaces.container import IContainer
+from types import StringTypes
+from zope.app.interfaces.container import UnaddableError
+
+class SampleContainer(object):
+ """Sample container implementation suitable for testing.
+
+ It is not suitable, directly as a base class unless the subclass
+ overrides _Container__newData to return a persistent mapping
+ object.
+ """
+
+ __implements__ = IContainer
+
+ def __init__(self):
+ self.__data = self._Container__newData()
+
+ def _Container__newData(self):
+ """Construct an item-data container
+
+ Subclasses should override this if they want different data.
+
+ The value returned is a mapping object that also has get,
+ has_key, keys, items, and values methods.
+ """
+ return {}
+
+
+ def keys(self):
+ '''See interface IReadContainer'''
+ return self.__data.keys()
+
+ def __iter__(self):
+ return iter(self.__data.keys())
+
+ def __getitem__(self, key):
+ '''See interface IReadContainer'''
+ return self.__data[key]
+
+ def get(self, key, default=None):
+ '''See interface IReadContainer'''
+ return self.__data.get(key, default)
+
+ def values(self):
+ '''See interface IReadContainer'''
+ return self.__data.values()
+
+ def __len__(self):
+ '''See interface IReadContainer'''
+ return len(self.__data)
+
+ def items(self):
+ '''See interface IReadContainer'''
+ return self.__data.items()
+
+ def __contains__(self, key):
+ '''See interface IReadContainer'''
+ return self.__data.has_key(key)
+
+ has_key = __contains__
+
+ def setObject(self, key, object):
+ '''See interface IWriteContainer'''
+ if not isinstance(key, StringTypes):
+ raise TypeError("The key must be an ascii or unicode string")
+ if len(key) == 0:
+ raise ValueError("The key cannot be an empty string")
+ self.__data[key] = object
+ return key
+
+ def __delitem__(self, key):
+ '''See interface IWriteContainer'''
+ del self.__data[key]
+
+ #
+ ############################################################
=== Zope3/src/zope/app/container/traversal.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/traversal.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# 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.0 (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.
+#
+##############################################################################
+"""Define view component for folder contents.
+
+$Id$
+"""
+
+from zope.publisher.interfaces.browser import IBrowserPublisher
+from zope.publisher.interfaces.xmlrpc import IXMLRPCPublisher
+from zope.publisher.interfaces import NotFound
+from zope.app.interfaces.container import ISimpleReadContainer, IItemContainer
+from zope.component import queryView
+from zope.component import getDefaultViewName
+
+
+class ContainerTraverser:
+
+ __implements__ = IBrowserPublisher, IXMLRPCPublisher
+ __used_for__ = ISimpleReadContainer
+
+ def __init__(self, container, request):
+ self.context = container
+ self.request = request
+
+ def publishTraverse(self, request, name):
+ c = self.context
+
+ subob = c.get(name, None)
+ if subob is None:
+
+ view = queryView(c, name, request)
+ if view is not None:
+ return view
+
+ raise NotFound(c, name, request)
+
+ return subob
+
+ def browserDefault(self, request):
+ c = self.context
+ view_name = getDefaultViewName(c, request)
+ view_uri = "@@%s" % view_name
+ return c, (view_uri,)
+
+
+class ItemTraverser(ContainerTraverser):
+
+ __used_for__ = IItemContainer
+
+ def publishTraverse(self, request, name):
+ context = self.context
+
+ try:
+ return context[name]
+
+ except KeyError:
+ view = queryView(context, name, request)
+ if view is not None:
+ return view
+
+ raise NotFound(context, name, request)
+
+
+"""
+Revision:
+$Id$
+"""
+
+from zope.app.interfaces.traversing.traversable import ITraversable
+from zope.app.traversing.exceptions import UnexpectedParameters
+from zope.app.interfaces.container import IReadContainer
+from zope.exceptions import NotFoundError
+from zope.component.exceptions import ComponentLookupError
+
+_marker = object()
+
+class ContainerTraversable:
+ """Traverses containers via getattr and get.
+ """
+
+ __implements__ = ITraversable
+ __used_for__ = IReadContainer
+
+ def __init__(self, container):
+ self._container = container
+
+
+ def traverse(self, name, parameters, original_name, furtherPath):
+ if parameters:
+ raise UnexpectedParameters(parameters)
+
+ container = self._container
+
+ v = container.get(name, _marker)
+ if v is _marker:
+ v = getattr(container, name, _marker)
+ if v is _marker:
+ raise NotFoundError, original_name
+
+ return v
=== Zope3/src/zope/app/container/zopecontainer.py 1.1 => 1.2 ===
--- /dev/null Wed Dec 25 09:13:47 2002
+++ Zope3/src/zope/app/container/zopecontainer.py Wed Dec 25 09:12:46 2002
@@ -0,0 +1,138 @@
+##############################################################################
+#
+# 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.0 (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.
+#
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from zope.app.interfaces.container import IZopeContainer
+from zope.app.interfaces.container import IOptionalNamesContainer
+from zope.app.interfaces.container import IContainerNamesContainer
+from zope.component import queryAdapter
+from zope.proxy.context import ContextWrapper
+from zope.event import publish
+from zope.app.event.objectevent \
+ import ObjectRemovedEvent, ObjectModifiedEvent, ObjectAddedEvent
+from zope.app.interfaces.container import IAddNotifiable
+from zope.app.interfaces.container import IDeleteNotifiable
+from types import StringTypes
+from zope.proxy.introspection import removeAllProxies
+
+_marker = object()
+
+class ZopeContainerAdapter:
+
+ __implements__ = IZopeContainer
+
+ def __init__(self, container):
+ self.context = container
+
+ def __getitem__(self, key):
+ "See IZopeItemContainer"
+ value = self.context[key]
+ return ContextWrapper(value, self.context, name=key)
+
+ def get(self, key, default=None):
+ "See IZopeSimpleReadContainer"
+ value = self.context.get(key, _marker)
+ if value is not _marker:
+ return ContextWrapper(value, self.context, name=key)
+ else:
+ return default
+
+ def __contains__(self, key):
+ '''See interface IReadContainer'''
+ return key in self.context
+
+
+ def values(self):
+ "See IZopeReadContainer"
+ container = self.context
+ result = []
+ for key, value in container.items():
+ result.append(ContextWrapper(value, container, name=key))
+ return result
+
+ def keys(self):
+ '''See interface IReadContainer'''
+ return self.context.keys()
+
+ def __len__(self):
+ '''See interface IReadContainer'''
+ return len(self.context)
+
+ def items(self):
+ "See IZopeReadContainer"
+ container = self.context
+ result = []
+ for key, value in container.items():
+ result.append((key, ContextWrapper(value, container, name=key)))
+ return result
+
+
+ def setObject(self, key, object):
+ "See IZopeWriteContainer"
+
+ if not isinstance(key, StringTypes):
+ raise TypeError("Item name is not a string.")
+
+ container = self.context
+
+ if not key:
+ if not (IOptionalNamesContainer.isImplementedBy(container)
+ or IContainerNamesContainer.isImplementedBy(container)):
+ raise ValueError("Empty names are not allowed")
+
+ # We remove the proxies from the object before adding it to
+ # the container, because we can't store proxies.
+ object = removeAllProxies(object)
+
+ # Add the object
+ key = container.setObject(key, object)
+
+ # Publish an added event
+ # We explicitly get the object back from the container with
+ # container[key], because some kinds of container may choose
+ # to store a different object than the exact one we added.
+ object = ContextWrapper(container[key], container, name=key)
+ publish(container, ObjectAddedEvent(object))
+
+ # Call the after add hook, if necessary
+ adapter = queryAdapter(object, IAddNotifiable)
+ if adapter is not None:
+ adapter.manage_afterAdd(object, container)
+
+ publish(container, ObjectModifiedEvent(container))
+ return key
+
+ def __delitem__(self, key):
+ "See IZopeWriteContainer"
+ container = self.context
+
+ object = container[key]
+ object = ContextWrapper(object, container, name=key)
+
+ # Call the before delete hook, if necessary
+ adapter = queryAdapter(object, IDeleteNotifiable)
+ if adapter is not None:
+ adapter.manage_beforeDelete(object, container)
+
+
+ del container[key]
+
+ publish(container, ObjectRemovedEvent(object))
+ publish(container, ObjectModifiedEvent(container))
+
+ return key